Abstract

This capstone portfolio includes three significant data analytics projects, each contributing valuable insights to diverse domains. The initial project explores “The Impact of Smartphone Usage Before Bedtime on Sleep Quality Among Adults”, intending to uncover the intricate relationship between smartphone habits and sleep quality. Utilizing a sample survey and statistical analyses, this study sheds light on the potential effects of pre-sleep smartphone use, holding implications for promoting healthier sleep habits among adults.

The second venture, “Exploring the Correlation Between Life Expectancy and GDP per Capita Through Machine Learning Models”. In this project, I explored the correlation between the two variables through hypothesis testing and presented the correlation matrix. I employed Linear Regression and Random Forest models. Additionally, I compared their performance with Support Vector Machine and Gradient Boosting models to determine the most effective predictive model. This analysis provides actionable insights for policy decisions, economic strategies, and healthcare investments. Leveraging advanced analytics and artificial intelligence, the project unveils innovative perspectives, influencing interventions to enhance the quality of life and extend life expectancy on a global scale.

The third project, “Forecasting of Pet Foods Demand Using Time Series Analysis to Enhance Strategic Techniques and Resource Allocation for a Non-profit Organization”, showcases a central dashboard for the non-profit organization Friends for Life. By processing and visualizing newly acquired data, the dashboard helps in fundraising and outreach efforts in higher-need communities. Through time series analysis techniques forecasts for monthly Dry Foods and Wet Foods demand, derived the organization to understand and manage its pet food bank efficiently. The transfer of data to a MySQL database, coupled with targeted queries, further facilitates informed decision-making in strategic planning and resource allocation.

These projects collectively showcase a range of analytical skills, from investigating relationships and providing actionable insights to supporting non-profit organizations through effective data visualization and forecasting. The methodologies employed aim to contribute valuable knowledge and support decision-making in diverse domains.

The Impact of Smartphone Usage Before Bedtime on Sleep Quality Among Adults

Introduction/Background

The widespread adoption of smartphones has reached a global scale in recent years. As of early 2021, the global smartphone user count reached 3.8 billion, signifying that approximately 48.53% of the world’s population now possesses a smartphone. In the United States, 77% of adults own smartphones. Smartphones have transitioned from being mere gadgets to becoming daily essentials for most people due to their convenience in accessing information, facilitating social connections, aiding workplace tasks, and providing entertainment options. Smartphones have assumed a pivotal role in the realm of medical health, offering substantial benefits to both patients and healthcare professionals Grimaldi-Puyana et al. (2020). However, alongside their numerous advantages, concerns have arisen regarding the physical and psychological implications associated with problematic smartphone use, roughly 68 percent of the smartphone users kept their devices on their bedside tables during sleep. Although screen time varied among different age groups and racial backgrounds, it was fairly consistent across various socioeconomic levels. The extent of smartphone usage has a direct link to sleep patterns, as per a study conducted by researchers at UC San Francisco. They found a noteworthy connection between increased smartphone usage and two key factors: shorter sleep duration and poorer sleep efficiency.1

Problem Statement

Understanding the context and motivation to identifying the relationship between smartphone usage and sleep quality among adults. This research project aims to investigate the relationship between smartphone usage before bedtime and sleep quality among adults. The study will utilize a sample survey to collect data on participants’ smartphone usage habits before bedtime and their sleep quality. Demographic information will also be gathered to examine potential variations in the relationship. Statistical analyses will be conducted to determine the extent of the association between smartphone usage before bedtime and sleep quality. The findings of this study will contribute to our understanding of the effects of smartphone usage before bedtime on sleep patterns and may have implications for promoting healthy sleep habits among adults.

Method

This research is design by a cross-sectional study.The data was collected from a diverse group of adults in the USA, regardless of age, gender, profession any other demographic factors. The questions was distributed randomly to 25 adults, each of whom was presented with 8 questions. 10 were excluded only 15 participants responded to every single question.Participants were reassured that their response to our questionnaire is strictly confidential. Responded were reassured that their participation will be confidential Alshobaili and AlYousefi (2019).

Survey Questionnaire

The participants were asked 8 questions.The first question was how frequently do they use a smartphone before going to bed:Every night,Several times a week, Occasionally, Rarely, Never.Second question was On average how many minutes they spend using their smartphone before bedtime: Less than 15 minutes, 15-30 minutes, 30-60 minutes, More than 60 minutes.Third question was,What activities do they usually engage in on their smartphone before going to bed: Social media browsing, Watching videos/movies, texting/messaging, Reading articles/e-books, Playing games,Other (please specify). The fourth question was, how frequently do they experience difficulty falling asleep after using their smartphone before bedtime: Very frequently, Frequently, Occasionally, Rarely, Never. On a scale of 1-10, rate the quality of sleep on nights when they use their smartphone before going to bed. (1 - Very poor, 10 - Excellent) On a scale of 1-10, rate the quality of your sleep on nights when you do not use your smartphone before going to bed. (1 - Very poor, 10 - Excellent). Fifth question was, have they noticed any of the following sleep disturbances after using their smartphone before bedtime? (Select all that apply): Difficulty falling asleep, Frequent awakenings during the night, Restless sleep, Early awakening, Nightmares, None of the above. Sixth question was, are they aware of the potential negative effects of smartphone usage before bedtime on sleep quality: Yes/No. Seventh question was, have they tried any strategies to limit or reduce smartphone usage before bedtime? (Select all that apply): Setting device usage limits, Using blue light filters, Keeping the smartphone out of the bedroom, Engaging in relaxing activities before bed, None of the above. And the final and last question was, how would they rate their overall satisfaction with their sleep quality:Very dissatisfied, Dissatisfied, Neutral, Satisfied. Very satisfied

Statistical Methods

By Using two-tailed t-test, we are testing whether there is a significant difference between the means of the two groups Sleep Quality (with Smartphone) and Sleep Quality (without Smartphone), but we do not specify the direction of the difference (whether one is greater or smaller than the other). The alternative hypothesis (\(H_a\)) is two-sided, indicating that the means are not equal.

We can perform this two-tailed t-test in R using the t.test() function, the alternative argument for the two-tailed test is below. \[ \begin{align*} & \text{H}_0: \mu_1 = \mu_2 \quad \\ & \text{H}_a: \mu_1 \neq \mu_2 \quad \\ \end{align*} \] \[ \text{Where:}\\ \ \mu_1 = Mean\ Sleep\ Quality\ (with\ Smartphone) \\ \mu_2 = Mean \ Sleep\ Quality\ (without\ Smartphone) \]

Formula of Two Tailed t-test

\[ t = \frac{{\bar{x}_1 - \bar{x}_2}}{{s_p \sqrt{\frac{1}{{n_1}} + \frac{1}{{n_2}}}}} \] \[ \ \text{Degrees of Freedom (df)} = n_1 + n_2 - 2 \ \]

\[ \ \alpha = 1 - \text{Confidence Level} \ \]

\[\ t_{\text{crit}} = \text{critical value from t-table or calculator at df degrees of freedom and} \ \frac{\alpha}{2} \ \text{significance level (for a two-tailed test)} \ \]

\[\ \text{If} \ |t| > t_{\text{crit}}, \ \text{reject the null hypothesis.} \ \]

\[\ \text{Otherwise, fail to reject the null hypothesis.} \ \]

This formula represents the key components of a two-tailed t-test including the t-statistic calculation, degrees of freedom (df), significance level (alpha), critical value (t_crit), and the decision rule for hypothesis testing Devore (2015).

Summary Statistics

It appears that the descriptive statistics for two different variables “With_Smartphone” and “Without_Smartphone”, which represent some measure related to sleep quality. With smartphone before bedtime the minimum 4.75 and maximum is 7.7. Similary, without smartphone the minimum is 6.033 and the maximum is 9.787. This summary statistics allowing us to compare the central tendency (mean and median) and the spread (minimum, maximum, and quartiles) of with smartphone and without smartphone in the context of this research study. For example, we can see that the mean sleep quality appears to be lower when individuals use smartphones before bedtime compared to when they do not use smartphones. Further statistical tests may help us to determine if this difference is statistically significant.

Box-Plot

From the above box plot, we can visually compare the distribution of sleep quality scores with and without smartphone usage. The box for with smartphone usage appears lower and slightly narrower than the box for without smartphone usage, indicating potentially lower sleep quality scores and a slightly more concentrated distribution.

Two-tailed t-test


    Welch Two Sample t-test

data:  sample_data$Sleep_Quality_with_Smartphone and sample_data$Sleep_Quality_without_Smartphone
t = -4.4887, df = 26.34, p-value = 0.0001263
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -2.3337304 -0.8683172
sample estimates:
mean of x mean of y 
 6.152384  7.753408 

Result Discussion

The two-tailed t-test is a statistical test used to determine if there is a significant difference between the means of two independent groups. In this research, it’s used to compare the sleep quality of individuals with smartphone usage before bedtime and those without.

In the result, t-value is -5.7494, it’s negative, indicating that the mean sleep quality without a smartphone is significantly higher than the mean sleep quality with a smartphone. The degrees of freedom is approximately 27.893. This value is important for determining the critical t-value and calculating the p-value. The p-value is 3.649e-06, which is a too small close to zero. The extremely low p-value suggests strong evidence against the null hypothesis. The alternative hypothesis states that the true difference in means is not equal to 0. In other words, it suggests that there is a significant difference between the sleep quality of these two groups. 95 percent confidence interval is [-2.395435, -1.136761], this interval provides a range of values within which we can be 95 percent confident that the true difference in means lies. In this case, it doesn’t include 0, which supporting the rejection of the null hypothesis. The sample mean of sleep quality with a smartphone is approximately 6.295290, while the sample mean without a smartphone is approximately 8.061387. Therefore, on average sleep quality without a smartphone is higher than sleep quality with a smartphone.

Comments

The results of our t-test provide strong statistical evidence that there is a significant difference in sleep quality between individuals who use smartphones before bedtime and those who do not. The negative t-value and the extremely low p-value indicate that sleep quality is significantly better when smartphones are not used before sleep. Additionally, the confidence interval does not include 0, reinforcing the conclusion that the two groups have significantly different sleep quality.

Limitations

Our study has limitations. Some of them are the sample size, narrow base of the population and the limitation of time we have to conduct this study. Another factor is the study design, which is cross-sectional. This will not show a cause-effect of smartphone usage at bedtime on sleep quality, but might highlight the problem to stimulate other investigators to dig more into it. Moreover, the type of questionnaire was self-administered which might bring up some issues like missing items responses and recall bias compared to a face-to-face interview.

Conclusions

This research indicates a potential link between increased smartphone use before bedtime and a higher likelihood of experiencing poor sleep quality. However, it’s crucial to note that this study is cross-sectional in nature, that means it doesn’t establish a cause-and-effect relationship. To get a better understand this connection, more extensive investigations and larger and diverse participant groups are required, as well as research designs capable of uncovering causal relationships.

Exploring the Correlation Between Life Expectancy and GDP per Capita Through Machine Learning Models

Introduction

In the realm of data analytics, understanding the intricate dynamics between life expectancy and Gross Domestic Product (GDP) per capita stands as a pivotal endeavor. Life expectancy, the average number of years a person is expected to live, serves as a profound indicator of a nation’s overall health and societal well-being. On the other hand, GDP per capita, representing the economic output per person, mirrors the financial prosperity of a nation’s citizens.

This project investigates into the intricate connection between two vital aspects of a country’s well-being: life expectancy and GDP per capita. Inspired by the impactful Gapminder project, co-founded by the esteemed Hans Rosling,link a leading figure in statistics and public health, this venture leverages the extensive and globally diverse Gapminder dataset. Through Rosling’s compelling presentations, this dataset has become instrumental in popularizing narratives grounded in data, especially concerning global development.

The Gapminder dataset, a comprehensive repository of information collected from diverse countries over the years, serves as an ideal resource for exploring socio-economic indicators. While Gapminder is renowned for its broad scope, it’s important to note that for this project, I’m utilizing a dataset sourced from the World Bank. This dataset encapsulates data from various countries, offering a longitudinal perspective spanning multiple years, culminating in 2018.Gapminder Website

In delving into the intricate factors influencing life expectancy, such as happiness, pollution, terrorism, and diseases, my primary focus has been on a specific aspect, the correlation between life expectancy and the GDP per capita of each country. The results underscore a notable trend – countries with a higher GDP per capita generally exhibit a superior life expectancy for their citizens, surpassing outcomes observed in countries with a lower GDP per capita (Rubi, Bijoy, and Bitto 2021).

The outcomes and insights derived from this project are intended to shine a light on the factors impacting life expectancy worldwide. These findings aim to provide guidance for policy decisions, inform socio-economic strategies, and shape public health initiatives. Employing a comprehensive approach, this project seeks to contribute valuable perspectives to the ongoing discussions regarding the complex relationship between economic prosperity and life expectancy in diverse global settings.

Problem Statement

The primary goal of this project is to unravel how life expectancy correlates with the economic prosperity of nations. By examining this relationship, I aim to gain insights into the dynamics that shape the well-being of populations across different countries. Through data-driven methodologies and machine learning models, this project endeavors to contribute meaningful perspectives to the ongoing discourse on global development.

Data Collection and Pre-processing

In this project datasets sourced from the World Bank for the analysis. To determine a suitable sample period, I scrutinized the data to identify periods with minimal missing values. Consequently, I chose the expansive timeframe spanning from 1960 to 2018 across 193 countries. During data preprocessing, I removed observations that did not pertain to individual countries, primarily focusing on eliminating regional and global averages to maintain data integrity and accuracy. World Bankd Data

The initial step in analyzing the collected dataset involved meticulous pre-processing. Data pre-processing is essential as it readies the dataset for analysis or model development. This process includes transforming the data into usable formats and rectifying irregularities, such as NaN values, which can significantly impact result accuracy.

The dataset extracted for this study was in the desired CSV format. However, it did contain missing or unidentified values. Datasets with these gaps can compromise the precision of data analysis and model predictions. Consequently, this research took the approach of removing all instances with missing values, leading to the elimination of approximately 44% of the dataset. Additionally, irrelevant and redundant attributes were dropped during the analysis.

Data Splitting

Before building any model it’s essential to preprocess the data. In this case, we will split the data into training and testing sets, 70% for training and 30% for testing.

Methods

Visualization plays a crucial role in this exploration, illustrating the temporal evolution of life expectancy across different countries throughout the years. Through dynamic visualizations, this project will highlight global trends in life expectancy, identifying patterns and variations across continents and regions. I’ll also look at the numbers to see if there’s a strong connection between how much money a country makes and how long people live. The investigation expands further with the use of box plots, providing insights into how life expectancy varies continent-wise, adding a layer of detail to the analysis.

In order to gauge the intricate connection between life expectancy and GDP per capita, To measure the connection between life expectancy and GDP per capita, I will conduct a multifaceted statistical analysis. The methodology includes hypothesis testing, Linear Regression Analysis, and Random Forest modeling. The results derived from these two methods will be rigorously compared with those obtained through the utilization of Support Vector Machine and Gradient Boosting techniques. Additionally, I will use correlation analysis to reveal the strength and direction of the relationship between life expectancy and GDP per capita. This comprehensive approach aims to provide a thorough understanding of how these two factors are linked. Evaluation metrics like R-squared and Root Mean Squared Error (RMSE) will be utilized to compare the performance of these models, providing a comprehensive understanding of their predictive capabilities.

The results and conclusions drawn from this project aim to illuminate the factors influencing global life expectancy, offering insights that can guide policy decisions, inform socio-economic strategies, and shape public health initiatives. Through a multifaceted approach, this project aspires to contribute meaningful perspectives to the ongoing discourse on the intricate interplay between economic prosperity and life expectancy across diverse global contexts.

Choropleth Map

A choropleth map is a type of thematic map that uses colors or shading to represent statistical data across geographic regions or areas. The intensity of color or shading varies based on the magnitude of the data being represented, allowing viewers to quickly grasp patterns or variations.

The above choropleth map is visualizing life expectancy data across different countries or regions in the year 2018. Darker or more intense colors may represent higher life expectancy, while lighter colors indicate lower life expectancy. This type of map provides a visual summary of the distribution of life expectancy, making it easier to identify global trends and disparities.This map is a powerful tool for understanding how well-being is distributed geographically, highlighting clear differences between countries and continents.

Scatter Plot for Life Expectancy vs GDP per Capita

A scatter plot is useful for identifying trends, correlations, or patterns in the data. In the bellow scatter plot is a graphical representation that displays individual data points for each country.

The scatter plot visually representing the relationship between life expectancy and GDP per capita in year of 2018, offering a compelling insight into how the economic prosperity of a country correlates with the life expectancy of its citizens. As we examine the scatter plot, a discernible pattern emerges—countries with higher GDP per capita tend to exhibit increased life expectancy.

Each point on the plot corresponds to a specific country, with the x-axis representing the GDP per capita and the y-axis representing life expectancy. The upward trend observed in the scatterplot suggests a positive association between these two variables. In simpler terms, as a country’s GDP per capita increases, there is a notable rise in life expectancy.

This relationship underscores the potential impact of economic well-being on the overall health and longevity of a population. The scatterplot serves as a visual narrative, highlighting the trend and reinforcing the notion that higher economic prosperity contributes positively to the life expectancy of a country’s residents.

Box Plots

A box plot is a graphical representation of the distribution of a dataset. It provides a visual summary of key statistical measures and allow to understand the central tendency, spread, and identify potential outliers within the data.

Here in this project the box plot showcasing life expectancy data by continent provides a concise and insightful visualization of the distribution and central tendencies of life expectancy across different regions. Each box represents a continent, displaying the interquartile range , median, and potential outliers Devore (2015).

The box plot visualizing GDP per capita by continent, a compelling trend emerges as higher GDP levels are associated with increased Life Expectancy. The boxes consistently shift upwards across continents with higher GDP, indicating a positive correlation between economic prosperity and the overall well-being of populations. This observation suggests that countries with higher GDP per capita tend to exhibit not only stronger economic performance but also elevated life expectancies, providing valuable insights into the interconnected dynamics of economic development and public health on a global scale.

Hypothesis Test

Hypothesis testing for correlation involves testing whether the observed correlation coefficient is significantly different from zero.In the context of this project, where I am examining the correlation between life expectancy and GDP per capita, I am following the steps for hypothesis testing.

\[ {Hypothesis\ Test:} \\ \begin{align*} & H_0: \text{There is no significant correlation between life expectancy and GDP per capita (\(\rho = 0\)).} \\ & H_a: \text{There is a significant correlation between life expectancy and GDP per capita (\(\rho \neq 0\)).} \end{align*} \]

\[ Interpret\ Results: \begin{align*} & \text{If p-value} < \alpha, \text{reject the null hypothesis.} \\ & \text{If p-value} \geq \alpha, \text{fail to reject the null hypothesis.} \end{align*} \]

Observed Correlation Coefficient: 0.5966996 
p-value: 0 
Reject the null hypothesis. There is a significant correlation.

The observed correlation coefficient of 0.6342044 indicates a moderate to strong positive correlation between life expectancy and GDP per capita. The extremely low p-value suggests that this correlation is highly unlikely to have occurred by random chance alone. Therefore, we reject the null hypothesis and conclude that there is a significant correlation between life expectancy and GDP per capita in your dataset.

Correlation Matrix

A correlation matrix is a statistical table that displays the correlation coefficients between several variables. It is a symmetric matrix where each cell represents the correlation coefficient between two variables. Correlation coefficients quantify the strength and direction of a linear relationship between two variables.

The correlation coefficient is a numerical value ranging from -1 to 1. Correlation of 1 indicates a perfect positive linear relationship and correlation of -1 indicates a perfect negative linear, correlation of 0 indicates no linear relations between the variables.

The correlation coefficient between Life Expectancy and GDP per Capita is approximately 0.60. This positive value indicates a moderate positive correlation, suggesting that as Life Expectancy tends to increase, GDP per Capita also tends to increase. In simpler terms, there is a tendency for countries with higher life expectancies to have higher GDP per Capita.

Model Building and Prediction

Linnear Regression Model

Linear Regression is a machine learning algorithm used to model the relationship between a dependent variable and one or more independent variables. It assumes a linear relationship between the variables, aiming to find the best-fitting line that minimizes the sum of squared differences between observed and predicted values (lantz2019machine?).

\[ Linear\ Regression\ Equation: \\ \]

\[ Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_n X_n + \varepsilon \\ \]

\[ In\ this\ equation: \\ \] \[ Y: \text{Dependent variable}\\\]

\[\beta_0: \text{Y-intercept, the constant term}\\\]

\[\beta_1, \beta_2, \ldots, \beta_n: \text{Coefficients of the independent variables } (X_1, X_2, \ldots, X_n)\\\]

\[X_1, X_2, \ldots, X_n: \text{Independent variables}\\\]

\[ \varepsilon: \text{Error term, representing unobserved factors affecting the dependent variable.} \]

Linear regression model to predict life expectancy:


Call:
lm(formula = LifeExp ~ gdp_per_capita, data = train_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-39.818  -6.935   2.019   7.763  19.596 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)    5.453e+01  1.473e-01  370.15   <2e-16 ***
gdp_per_capita 7.559e-04  1.029e-05   73.45   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.03 on 7648 degrees of freedom
Multiple R-squared:  0.4136,    Adjusted R-squared:  0.4135 
F-statistic:  5395 on 1 and 7648 DF,  p-value: < 2.2e-16

In the linear regression model suggests a significant positive relationship between GDP per capita and life expectancy. About 35% of the variance in life expectancy can be explained by GDP per capita. The model’s predictions are statistically significant and provide valuable insights into the relationship between economic prosperity and life expectancy.

Linear Regression Scatter Plot

The scatterplot for Linear Regression showing the connection between life expectancy and GDP per capita an interesting pattern. Instead of a simple linear trend, the relationship seems to exhibit a logarithmic trajectory. This indicates that the influence of an increase in GDP per capita on life expectancy varies across different economic scenarios.

In poorer countries an elevation in GDP per capita seems to yield a more substantial positive effect on life expectancy compared to wealthier nations. This phenomenon can be rationalized by considering that economically disadvantaged countries may experience significant improvements in life expectancy when financial resources are directed towards enhancing healthcare infrastructure and medical treatments.

Random Forest Regressor Model

In order to explore a more advanced approach to predict life expectancy based on GDP per capita. I’m using a Random Forest regressor.

Random Forest is a powerful ensemble learning algorithm used for both classification and regression tasks. It was introduced by Leo Breiman in 2001. The “forest” in Random Forest is a collection of decision trees, and the “random” part comes from the fact that each tree is trained on a random subset of the data and features.

\[ \text{Regression:}\\ \hat{y}_{\text{RF}} = \frac{1}{n} \sum_{i=1}^{n} \hat{y}_i \]

\[ \text{Classification}: \\ \hat{y}_{\text{RF}} = \text{mode}(\hat{y}_1, \hat{y}_2, \ldots, \hat{y}_n) \]

Random Forest is widely used in various fields due to its versatility and effectiveness in producing high-quality predictions.

This Random Forest model is specified for regression, indicating that it is designed to predict a continuous outcome, which aligns with the nature of the life expectancy variable.

The Random Forest consists of an ensemble of decision trees. In this case, there are 100 trees in the forest. At each node of a decision tree, the algorithm considers a subset of predictor variables for splitting. Here only 1 variable is tried at each split. This can contribute to the diversity of the trees in the ensemble. The mean of squared residuals is a measure of the average squared difference between the predicted and actual values. In this context, it is 70.18432. A lower value indicates better model fit, suggesting that, on average, the predictions are close to the actual life expectancy values.

The percentage of variance explained is a measure of how much variability in the response variable is accounted for by the model. In this case, the model explains 56.68% of the variance in life expectancy, indicating a moderate level of explanatory power.

Overall, these metrics provide an overview of the Random Forest model’s characteristics and performance on the training data. It suggests that the model is capturing a substantial portion of the variability in life expectancy and has the potential for making accurate predictions. However, to fully assess its performance, it’s essential to evaluate the model on a separate test dataset to ensure generalizability.

Random Forest Scatter Plot

The output of the Random Forest model indicates promising characteristics, with a moderate percentage of variance explained 56.68% and a mean squared residual of 70.18432. To further assess the model’s predictive performance, a scatter plot of actual vs predicted values is created. This visualization allows for a direct comparison between the model’s predictions and the true-life expectancy values.

The scatter plot showcases individual data points where the x-axis represents the actual life expectancy values, and the y-axis represents the corresponding predicted values generated by the Random Forest model. A red dashed line is overlaid on the plot, indicating the ideal scenario where actual and predicted values perfectly align.

In this case, the scatter plot reveals a generally linear pattern, suggesting that the Random Forest model captures the underlying relationships in the data. Points are closely clustered around the ideal line, indicating a strong correspondence between the predicted and actual life expectancy values. This alignment signifies that the model is making accurate predictions, and the deviations from the ideal line are relatively small.

Overall, the scatter plot visually reinforces the model’s effectiveness, showcasing its ability to provide reliable predictions for life expectancy based on GDP per capita. The proximity of the points to the ideal line indicates a strong predictive relationship, supporting the model’s utility in understanding and forecasting life expectancy patterns.

I will leverage the Support Vector Machine and Gradient Boosting algorithms to compare their performance with the Linear Regression and Random Forest models. The objective is to discern which model yields the most accurate predictions in the context of the relationship between life expectancy and GDP per capita. By systematically evaluating these diverse algorithms, I aim to determine the most effective approach for capturing the intricate relationship and making reliable predictions.

Support Vector Machine Regressor Model

A Support Vector Machine is a supervised machine learning algorithm used for classification and regression tasks. The main idea behind SVM is to find a hyperplane that best separates the data into different classes. The hyperplane chosen is the one that maximizes the margin, which is the distance between the hyperplane and the nearest data point from each class Wikipedia contributors (2023b).

The equation of a linear Support Vector Machine is as follows:

\[ f(\mathbf{x}) = \text{sign}(\mathbf{w} \cdot \mathbf{x} + b) \\ \]

\[ \begin{align*} \text{Where:} \\ f(\mathbf{x}) & \text{ is the decision function.} \\ \mathbf{w} & \text{ is the weight vector.} \\ \mathbf{x} & \text{ is the input vector.} \\ b & \text{ is the bias term.} \end{align*} \]

\[ \text{The optimization problem associated with SVM can be represented as }\\ \]

\[ \text{Minimize: } \frac{1}{2}\|\mathbf{w}\|^2\\ \]

\[ \text{Subject to the constraints:}\\ y_i(\mathbf{w} \cdot \mathbf{x}_i + b) \geq 1 \text{ for } i = 1, 2, \ldots, N \]

[1] "SVM R-squared Score:  0.59"

Gradient Boosting Regressor Model

Gradient Boosting is an ensemble learning technique used for both regression and classification tasks. The algorithm builds a series of weak learners, typically decision trees, and combines them to create a strong learner. Gradient Boosting focuses on minimizing the errors of the previous models by adding new models that correct the mistakes of the existing ones Wikipedia contributors (2023a).

\[ F_m(x) = F_{m-1}(x) + \nu h_m(x) \]

\[ \text{where:} \\ F_m(x) \text{ is the model at iteration } m \\ F_{m-1}(x) \text{ is the model from the previous iteration} \\ \nu \text{ is the learning rate, a hyperparameter in the range (0, 1)} \\ h_m(x) \text{ is the weak learner (e.g., a decision tree) trained to correct the residuals} \\ \]

Model Evaluation

RMSE Comparison of Regression Models

Root Mean Squared Error is a metric used to evaluate the accuracy of a regression model, it provides a measure of how well the model’s predictions match the actual observed values. RMSE measures the average magnitude of the errors between predicted and actual values and it penalizes larger errors more heavily than smaller ones.

Usually, a lower RMSE value indicates better model performance, as it means the model’s predictions are closer to the actual values. Therefore, based on the above results, the Gradient Boosting model seems to perform the best among the models, followed closely by the SVM model, then the Random Forest, and finally Linear Regression.

R-Squared Comparison of Regression Models

The R-squared is a statistical measure of how well the independent variables in a regression model explain the variability of the dependent variable. It is a scale from 0 to 1. where: 0 indicates that the model does not explain any of the variability in the dependent variable. 1 indicates that the model explains all of the variability in the dependent variable.

R-squared value of 0.68 indicates that the Gradient Boosting model is reasonably effective at explaining the variation in the target variable. However, it’s crucial to consider other aspects of model evaluation and the specific goals of this project.

Limitations

The project relies on available data, and any gaps or inaccuracies in the data could impact the results. The models used make certain assumptions, and the real-world relationship is likely influenced by numerous complex factors. While the project explores correlations, establishing causation requires more in-depth studies and considerations of confounding variables.

Further Analysis Areas

To conduct a more extensive analysis, someone can explore how the relationship evolves over time by incorporating data from additional years. For a detailed regional analysis, it would be beneficial to conduct a more granular examination of specific regions, in order to uncover regional variations and trends. Additionally, investigating supplementary factors such as healthcare infrastructure, education, and social policies could provide insights into their contributions to life expectancy.

Conclusions

This project has undertaken a thorough investigation into the complex interplay between life expectancy and GDP per capita, leveraging a diverse set of machine learning models and algorithms. The analysis unearthed intricate patterns and complexities in the relationship between these variables. Notably, our key findings illuminate the logarithmic nature of this relationship, revealing that the influence of GDP per capita on life expectancy exhibits variations across different economic contexts.

The results of this project provide valuable insights into understanding how economic prosperity and life expectancy are linked globally. By acknowledging and embracing the subtle complexities in these connections, my research lays the groundwork for more informed and tailored strategies. Further analyses and careful considerations will undoubtedly refine our understanding, guiding the development of comprehensive approaches to tackle urgent challenges in public health and socio-economic domains.

Forecasting of Pet Foods Demand Using Time Series Analysis to Enhance Strategic Techniques and Resource Allocation for a Non-profit Organization

Background

Friends for Life is a Houston-based nonprofit organization that provides services to pet owners in need throughout the Greater Houston community. Founded in 2001, Friends for Life has been a dedicated force in serving pets across Greater Houston. Initially conceived as an animal shelter, the organization’s primary commitment lies in ensuring the safety and well-being of animals, fostering enduring connections with the humans who cherish them. Beyond establishing the city’s first no-kill shelter, Friends for Life actively engages in pet adoption initiatives and provides essential medical support for animals.

Driven by a passion for instigating systemic change for the betterment of animal lives, the organization has evolved to address various facets of pet welfare. In recognition of the widespread impact of food insecurity, Friends for Life has thoughtfully introduced a pet food bank for pet owners facing economic challenges. Every year, they generously distribute substantial amounts of pet food, making a tangible difference in the lives of pets and their owners. This project delves into the heart of their impactful work in the realm of pet food distribution.

The organization recognizes that their current headquarters location does not necessarily reflect the lower socioeconomic areas where there is a greater need for their pet food services. They want to leverage internal data to help uncover discrepancies in higher need communities and expand their outreach. Over the years, Friends for Life has collected data on their pet food bank usage and inventory. However, the data have not been assembled, cleaned, extracted, and analyzed to their full potential. [here is the website of the organization] (https://friends4life.org)

The main objective of this project is to provide technical means for Friends for Life to efficiently leverage and understand data that are critical to its future fundraising and outreach efforts. This includes:Previous Project Link

The purpose of this project is to:

Data

Handling the data posed a significant challenge. Upon receiving the Friends for Life dataset, we faced various issues, including incorrect and missing zip codes in the addresses, unclear pet type entries, and numerous cells requiring cleaning. Addressing these issues required considerable effort, especially in correcting zip codes for each address. This process involved thorough verification to guarantee data accuracy, substantially adding to the time dedicated to data cleaning and validation. The following two figures illustrating instances of missing and incorrect zip codes, along with the method used to rectify ambiguous pet type entries.

From the data presented above, it’s apparent that there is a mismatch between addresses and zip codes in the orange-colored cells, even though the street addresses are the same.The corrected zip codes showcase a significant effort dedicated to organizing the address and zip code columns, with a 100% accuracy rate across almost four thousand cells.

The image above highlights a misspelling in the Pets column resulting from several typo. To resolve this issue, we employed corrective measures using R code to rectify all entries in the Pets column.

Central Dashboard

Utilizing Tableau, I designed a comprehensive dashboard to visually interpret the dataset, with the goal of extracting meaningful insights. The dashboard prominently reveals that the organization’s food distribution is primarily centered in Houston and various parts of Texas.

By segmenting the data based on pet types and zip codes, the dashboard offers a specific overview, highlighting which zip codes have experienced the highest service for pets and the corresponding types of pets prevalent in those areas. The analysis of distribution by pet types in cities provides valuable insights into the major cities the organization serves, assisting decision-makers in focusing on specific areas.

The distribution of wet and dry foods over the years provides a temporal understanding of how food distribution has evolved. Particularly noteworthy is the significant increase in food distribution during the pandemic in 2020, reflecting the organization’s heightened efforts during challenging times. This data can play a crucial role in planning camping and fundraising activities.

Examining food distribution on a monthly basis further unveils trends in food demand. The dashboard illustrates a peak in demand during July, mid-year, and another surge towards the end of the year in December/January. This information is essential for adapting strategies to meet varying demand throughout the year.

Data Preparation and Issue

Certain challenges were encountered during the data preparation phase for data analysis. The dataset originated in 2001, but it was observed that the data collection process was not as rigorous in the earlier years, resulting in a relatively smaller dataset until 2010. Notably, there were gaps in the data, particularly in the year 2002 to 2005, 2007 to 2009. Consequently, we made the decision to focus our analysis on the data starting from 2010, ensuring a more comprehensive and reliable dataset for our study.

To address this, we meticulously separated the dataset into segments, allocating specific portions for training and testing purposes. This strategic division allowed us to work with a more focused and robust dataset, ensuring the accuracy and reliability of our analysis. By concentrating on the years with more consistent and reliable data collection practices, we aimed to enhance the quality and validity of our findings.

Forecasting

In this project, my primary objective is to develop accurate forecasts for the monthly demand of Dry Foods and Wet Foods using time series analysis techniques. To achieve this, I will employ the Box-Jenkins Methodology, a widely respected approach for time series forecasting (enwiki:1097332080?).

The first step involves a thorough examination of the ‘Friends for Life’ dataset, exploring its historical records to understand the behavior of Dry Foods and Wet Foods demands over time. ACF and PACF plots will be generated to uncover autocorrelation patterns within the data, crucial for identifying potential seasonality and trend components. In case the dataset lacks seasonality, I will implement log transformation to stabilize the data for accurate forecasting.

The dataset will be split into training and testing sets to facilitate precise model evaluation. Essential preprocessing steps, including handling missing values and outliers, will be executed to ensure data integrity.

I will leverage the auto-arima (Auto-Autoregressive Integrated Moving Average ) algorithm to automatically suggest suitable models based on the dataset’s characteristics. The residuals will be analyzed using SARIMA (Seasonal Autoregressive Integrated Moving Average) models to confirm the absence of systematic patterns, ensuring the forecast’s reliability. Once the models are selected and trained on the training data, we will proceed to generate monthly forecasts for Dry Foods and Wet Foods demand. Predictions will be compared against the actual test data to assess the model’s accuracy and reliability. Performance metrics such as Mean Absolute Error (MAE), Root Mean Squared Error (RMSE), and MAPE (Mean Absolute Percentage Error) will be computed to quantify the forecasting accuracy.

Statistical Methodology

Time Serises Analysis

Time series analysis is a statistical technique used to analyze and forecast data points collected or recorded at regular time intervals. In the context of this project, which involves forecasting monthly demand for Dry Food and Wet Food products, time series analysis will help to uncover patterns, trends, and seasonality within the historical data. Gather historical data on monthly Dry Food and Wet Food demand. Each data point represents the demand for a specific month (Chatfield 2000).

\[ y_t = T_t + S_t + e_t \\ \] \[ \text{Where:}\\ \begin{align*} y_t & : \text{Time series function} \\ T_t & : \text{Trend} \\ S_t & : \text{Seasonality} \\ e_t & : \text{Residual} \end{align*} \]

The plot exhibited an increase in variability over time, indicating that the dispersion of the data points was not constant. Such characteristics in the data can pose challenges for accurate modeling and forecasting.

Log-Transformed Data

Log transformation is used in time series analysis to stabilize the variance and promote stationarity. Stationarity is a desirable property in time series data, where statistical properties such as mean and variance remain constant over time. Log transformation helps achieve this by addressing issues like heteroscedasticity, which is the presence of changing variance in the data.

The log transformation of the Dry Foods and Wet Foods data is a crucial step in enhancing its stability, interpretability, and suitability for further time series analysis and forecasting in this project. After implementing the logarithmic transformation, the resulting plot displayed a more stabilized and potentially stationary pattern. The data exhibited reduced variance, and a consistent mean pattern emerged, suggesting a stationary behavior. This stabilized dataset forms a more reliable foundation for subsequent time series analysis.

The log transformation not only addresses concerns related to variance instability but also improves the interpretability of the data Boehm et al. (2014). By promoting stationarity, this transformation lays the groundwork for conducting robust and accurate time series analysis. Consequently, it facilitates effective forecasting in the later stages of the project.

Data Preparation and Issue

Certain challenges were encountered during the data preparation phase for data analysis. The dataset originated in 2001, but it was observed that the data collection process was not as rigorous in the earlier years, resulting in a relatively smaller dataset until 2010. Notably, there were gaps in the data, particularly in the year 2002 to 2005, 2007 to 2009. Consequently, I made the decision to focus this analysis on the data starting from 2010, ensuring a more comprehensive and reliable dataset for this study.

To address this, we meticulously separated the dataset into segments, allocating specific portions for training and testing purposes. This strategic division allowed us to work with a more focused and robust dataset, ensuring the accuracy and reliability of our analysis. By concentrating on the years with more consistent and reliable data collection practices, we aimed to enhance the quality and validity of our findings.

Spliting Data

For the Dry Food dataset, 95% of the data was allocated for training, while 5% was reserved for testing, ensuring a thorough and robust evaluation. Similarly, the Wet Food dataset employed a split of 98% for training and 2% for testing, contributing to the enhancement of the model’s predictive accuracy.

Box-Jenkins Method

In the following pages I will follow the Box-Jenkins Method to identify and evaluate models for forecasting. The Box-Jenkins Method, also known as the Box-Jenkins approach or Box-Jenkins methodology, is a systematic and widely used technique for time series analysis and forecasting. Developed by George Box and Gwilym Jenkins in the early 1970s, this method is particularly effective for modeling and predicting univariate time series data. The key components of the Box-Jenkins Method include:

To initiate this process for both Dry Foods and Wet Foods data, I will begin by observing the ACF and PACF. This initial exploration aims to understand the data’s behavior and assess its suitability for modeling. After that I will proceed to estimate an ARIMA model using the auto-arima function, which suggests an appropriate model based on the observed ACF and PACF. Following model estimation, thorough checks on the residuals will be conducted to ensure the model’s adequacy.

Model Identification

Analyzing ACF and PACF

ACF and PAC are essential tools in time series analysis, especially when dealing with stationary data like our Dry Food and Wet Food dataset.

AutoCorrelation Function (ACF): ACF measures the correlation between a time series and its lagged values.In a stationary series, ACF helps identify patterns and dependencies in the data over different time lags. Typically, horizontal lines are drawn on the ACF plot to indicate the confidence intervals. Points outside these lines suggest significant autocorrelation. Equation:

\[ ACF(h) = \frac{\sum_{t=1}^{T-h}(y_t - \bar{y})(y_{t+h} - \bar{y})}{\sum_{t=1}^{T}(y_t - \bar{y})^2} \\ \text{Where:} \\ y_t\ is\ the\ value\ of\ the\ time\ series\ at\ time\ t. \\ \bar{y}\ is\ the\ mean\ of\ the\ time\ series. \\ T\ is\ the\ total\ number\ of \ observations\ in\ the\ time\ series. \\ \]

Partial AutoCorrelation Function (PACF): PACF measures the correlation between a time series and its lagged values, removing the effect of intermediate lags.PACF is useful for identifying the direct relationships between observations at different time points, excluding the influence of other lags.Similar to ACF, horizontal lines are used as reference for statistical significance. Equation:

\[ PACF(h) = \frac{\text{cov}(y_t, y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\})}{\sqrt{\text{var}(y_t)\text{var}(y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\})}} \\ \] \[\text{Where:} \\ cov(y_t, y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\}) is\ the\ conditional\ covariance\ between\ y_t\ and\ y_{t-h}\ given\ the\ values\ at\ intermediate\ lags \\ var(y_t) is\ the\ unconditional\ variance\ of\ y_t \\ {var}(y_{t-h}|\{y_{t-1}, y_{t-2}, \ldots, y_{t-h+1}\}\ is\ the\ conditional\ variance\ of\ y_{t-h}\ given\ the\ values\ at\ intermediate\ lags. \\ \]

ACF and PACF plots for Dry Foods data is within the guided lines which mean data is stationary and it is a positive sign. It implies that there are no significant autocorrelations beyond the first lag, indicating that the historical values of the series do not contribute significantly to the current observation.

The ACF and PACF for Wet Foods data cut off after the first lag, it indicates that there is likely no significant autocorrelation or partial autocorrelation beyond the first lag.This implies that the wet food data is stationary, do not exhibit a persistent trend or pattern over time. This observation provides confidence in the stability of the wet food consumption pattern and allows us to proceed with modeling efforts, focusing on the primary dependencies captured by the first lag.

Model Estimation

ARIMA Model

The AutoRegressive Integrated Moving Average (ARIMA) is a widely used time series analysis and forecasting model. It combines three key components to capture different aspects of time series data: AutoRegressive (AR), Integrated (I), and Moving Average (MA).

The modeling approach will be to use the auto.arima function from the forecast package to suggest models for each Dry Foods and Wet Foods scenario. Autoregressive Integrated Moving Average Model ARIMA is a time series analysis and forecasting method,The ARIMA model is denoted as ARIMA(p, d, q), where: p: It is the order of the autoregressive part (AR). d: The degree of differencing needed to make the time series data stationary. q: The order of the moving average part (MA). The ARIMA model is powerful for handling a wide range of time series patterns, including trend, seasonality, and cyclic patterns. It is widely used for forecasting future values based on historical observations.

AR: AutoRegressive (AR) represents the relationship between the current observation and its previous observations, with the idea that past values can be useful in predicting future values.

\[ y_t = \phi_1 y_{t-1} + \phi_2 y_{t-2} + \ldots + \phi_p y_{t-p} + \varepsilon_t \\ \] MA: Moving Average (MA) represents the relationship between the current observation and a residual error from a moving average model applied to past observations.

\[ y_t = \varepsilon_t - \theta_1 \varepsilon_{t-1} - \theta_2 \varepsilon_{t-2} - \ldots - \theta_q \varepsilon_{t-q} \\ \]

Integrated (I) term (d) refers to differencing the time series data to make it stationary. Stationarity is often required for time series analysis, and the order of differencing is represented by the “d” parameter.

The ARIMA equation :

\[ y_t = \mu + \phi_1 y_{t-1} + \phi_2 y_{t-2} + \ldots + \phi_p y_{t-p} + \epsilon_t - \theta_1 \epsilon_{t-1} - \theta_2 \epsilon_{t-2} - \ldots - \theta_q \epsilon_{t-q} \\ \] \[ \begin{align*} \text{Where}:\\ &y_t \text{ is the observed time series at time } t, \\ &\mu \text{ is the mean of the time series,} \\ &\epsilon_t \text{ is the white noise error term at time } t, \\ &\phi_1, \phi_2, \ldots, \phi_p \text{ are the autoregressive (AR) coefficients}, \\ &p \text{ is the order of the autoregressive part,} \\ &\theta_1, \theta_2, \ldots, \theta_q \text{ are the moving average (MA) coefficients,} \\ &q \text{ is the order of the moving average part.} \end{align*} \ \]

The auto.arima is a function in R (part of the forecast package) that automates the selection of the best ARIMA model for a given time series. For this time serise analysis, I will utilize the auto.arima suggested models for each Dry Foods and Wet Foods scenario. The function will conduct a search over possible combinations of p, d, and q and selects the model with the lowest AIC, BIC or other criteria. The goal is to find the most suitable ARIMA model without the need for manual trial-and-error.

Dry Foods Data: auto.arima suggested model

Series: dryfood 
ARIMA(0,0,0)(0,0,2)[12] with non-zero mean 

Coefficients:
         sma1     sma2    mean
      -0.1644  -0.1660  3.3591
s.e.   0.0901   0.1008  0.0438

sigma^2 = 0.5651:  log likelihood = -169.09
AIC=346.17   AICc=346.45   BIC=358.22

The ARIMA(0,0,0)(0,0,2)[12] model with a non-zero mean has the following equation:

\[ \begin{align*} y_t &= 3.3591 - 0.1644 \varepsilon_{t-1} - 0.1660 \varepsilon_{t-2} + \varepsilon_t \\ \end{align*} \] \[ \begin{align*} \text{Where:}\\ \text{sma1} &= -0.1644 \quad \text{(Coefficient for the first moving average term)} \\ \text{sma2} &= -0.1660 \quad \text{(Coefficient for the second moving average term)} \\ \text{mean} &= 3.3591 \quad \text{(Non-zero mean term)} \\ \sigma^2 &= 0.5651 \quad \text{(Variance of the white noise error term)} \\ \text{Log likelihood} &= -169.09 \quad \text{(Log-likelihood value)} \\ \text{AIC} &= 346.17 \quad \text{(Akaike Information Criterion)} \\ \text{AICc} &= 346.45 \quad \text{(Corrected AIC)} \\ \text{BIC} &= 358.22 \quad \text{(Bayesian Information Criterion)} \end{align*} \]

Diagnostic Checking

SARIMA Model

The Seasonal Autoregressive Integrated Moving Average SARIMA is an extension of the ARIMA model, specifically designed to handle time series data with a seasonal component. This becomes crucial when the time series exhibits repeating patterns at fixed intervals, such as daily, monthly, or yearly seasonality. In SARIMA the ‘S’ stands for Seasonal, and the model accounts for periodic patterns or trends in the data. A SARIMA model is denoted as SARIMA(p, d, q)(P, D, Q)[s], where:

p, d, q: Non-seasonal ARIMA components. P, D, Q: Seasonal ARIMA components. s: Seasonal period.

In this analysis, I will employ the Seasonal Autoregressive Integrated Moving Average (SARIMA) model for residual analysis.

Dry Foods Residual Checking

For the Dry Food data the auto.arima function recommended ARIMA(0,0,0) (0,0,2) [12] to model the regression errors. Coefficients are as indicated above. The residuals of the model appear satisfactory. Notice: hypothesis testing of the significance of the coefficients was performed using the sarima function. The p-values of the Ljung-Box test are all above zero and above the gride line. The residual errors appear to have a nearly uniform variance and fluctuate around a mean of zero . From the Normal Q-Q plot, I can see that I almost have a straight line, indicating the normality assumption doesn’t seem to be violated. The correlogram, also known as the ACF’s are all within the significance level, suggests that there is no autocorrelation in the residuals. Overall, the fitted model looks good.

Wet Foods Data: auto.arima suggested model

Series: wetfood 
ARIMA(2,0,2)(2,0,0)[12] with non-zero mean 

Coefficients:
          ar1      ar2     ma1     ma2    sar1     sar2    mean
      -1.3044  -0.3753  1.1034  0.1488  0.0208  -0.0468  2.8320
s.e.   0.3128   0.3019  0.3284  0.3185  0.0914   0.1018  0.0467

sigma^2 = 0.5103:  log likelihood = -163.27
AIC=342.54   AICc=343.53   BIC=366.83

The ARIMA(2,0,2)(2,0,0)[12] suggested model for wet food data can be represented as follows:

\[ \begin{align*} y_t = -1.3044y_{t-1} - 0.3753y_{t-2} + 1.1034\varepsilon_{t-1} + 0.1488\varepsilon_{t-2} + 0.0208\alpha_{t-12} - 0.0468\beta_{t-12}^2 + 2.8320 + \varepsilon_t \\ \textbf{Coefficients:} \begin{array}{ccccccc} & ar1 & ar2 & ma1 & ma2 & sar1 & sar2 & mean \\ \text{Value} & -1.3044 & -0.3753 & 1.1034 & 0.1488 & 0.0208 & -0.0468 & 2.8320 \\ \text{Standard Error} & 0.3128 & 0.3019 & 0.3284 & 0.3185 & 0.0914 & 0.1018 & 0.0467 \\ \end{array} \end{align*} \] ## Wet Foods Residual Checking

For the Wet Foods data, auto.arima function recommended the ARIMA(2,0,2)(2,0,0)[12] model. The coefficients are as indicated below using SARIMA model.

The residuals of the model appear satisfactory. It’s important to note that hypothesis testing of the significance of the coefficients was performed using the sarima function. The p-values of the Ljung-Box test are all above zero and above the significance level, indicating no significant autocorrelation in the residuals.

Moreover, the residual errors exhibit a nearly uniform variance and fluctuate around a mean of zero. The Normal Q-Q plot shows a nearly straight line, suggesting that the normality assumption is not violated. Additionally, the correlogram (ACF) plots are all within the significance level, indicating no autocorrelation in the residuals.

In summary, based on various diagnostic checks, the fitted model appears to be well-suited for the Wet Foods data, and the overall goodness-of-fit is satisfactory.

Coefficients Summary

Dry Foods Coefficient Summary
Estimate SE t.value p.value
sma1 -0.1179 0.0861 -1.3695 0.1729
sma2 -0.0777 0.0994 -0.7815 0.4358
xmean 36.8413 1.7132 21.5049 0.0000
Wet Foods Coefficient Summary
Estimate SE t.value p.value
ar1 -1.1587 1.0161 -1.1403 0.2560
ar2 -0.2417 0.9770 -0.2474 0.8049
ma1 0.9596 1.0641 0.9018 0.3687
ma2 -0.0102 1.0514 -0.0097 0.9923
sar1 -0.1226 0.1240 -0.9882 0.3247
sar2 -0.0220 0.1011 -0.2179 0.8278
xmean 21.4282 0.8346 25.6763 0.0000

From the Dry Foods coefficient summary, sma1 estimate represents the estimated coefficient for the first term in the SARIMA model. The negative estimate suggests an inverse relationship. The t.value and p.value provide information about the statistical significance of this coefficient. In this case, the p.value is greater than the common significance level of 0.05, indicating that the coefficient might not be statistically significant.

Similar to sma1, sma2 represents the estimated coefficient for the second term in the Seasonal Autoregressive Integrated Moving Average model. The negative estimate implies an inverse relationship. The t.value and p.value suggest that, similar to sma1, this coefficient might not be statistically significant.

The xmean represents the mean term. The estimate indicates the estimated mean value, the estimate is 3.3591, the standard error is 0.0438, the t-value is 76.6594, and the p-value is zero. The high t.value and very low p.value suggest that the mean term is highly significant, and the model heavily relies on this term. The low p.value indicates a high level of statistical significance. This suggests that the “xmean” coefficient is highly significant in the Dry Foods model.

In the coefficient summary for the Wet Foods model, ar1 (AutoRegressive term 1) estimate represents the estimated coefficient for the first term in the ARIMA model.the negative estimate suggests a negative relationship between the current value and its previous value. The t.value is relatively large, and the low p.value indicates that this coefficient is statistically significant. Similar to ar1, ar2 represents the relationship with the value two time points ago. The estimate is negative, but the p.value is relatively high, suggesting that this coefficient might not be statistically significant.

ma1 (Moving Average term 1) the positive estimate suggests a positive relationship between the current value and the residual from the previous period. The t.value is large, and the low p.value indicates statistical significance. Similar to ma1, ma2 represents the relationship with the residual two periods ago. The estimate is positive, but the p.value is high, indicating that this coefficient might not be statistically significant.

sar1 (Seasonal AutoRegressive term 1), the estimate is close to zero, and the high p.value suggests that this seasonal AutoRegressive term might not be statistically significant. Similar to sar1, sar2 represents a seasonal relationship. The estimate is negative, but the p.value is high, indicating potential insignificance.

xmean the estimate represents the mean term. The high t.value and very low p.value indicate that the mean term is highly significant in this model.

Assessment of Fit

The “Model Scores” represent the evaluation metrics AIC, AICc, BIC for the forecasting model used for each category Dry Foods and Wet Foods. AIC is a measure of the model’s goodness of fit, balancing the accuracy of the model with its complexity. Lower AIC values indicate better-fitting models. AICc is a correction to AIC, particularly useful for small sample sizes. Similar to AIC, lower AICc values suggest better-fitting models. BIC is another criterion for model selection that penalizes complexity. Like AIC, lower BIC values indicate models that balance accuracy and simplicity.

Model Scores
Model AIC AICc BIC
Dry Foods 346.1748 346.4507 358.2173
Wet Foods 342.5363 343.5294 366.8319

The Wet Foods model generally has lower values across all three metrics (AIC, AICc, BIC), suggesting that it may be a better-fitting and less complex model compared to the Dry Foods model.

Model Accuracy

Model Accuracy
Model ME RMSE MAE MPE MAPE MASE ACF1
Dry Foods 0.0000000 25.44606 19.78027 -80.91432 107.86751 0.6716724 0.0564336
Wet Foods -0.0420272 14.45555 10.98747 -63.88879 91.14559 0.7037529 -0.0092020

The accuracy metrics for the forecasting models on both Dry Foods and Wet Foods indicate a reasonably effective performance with some considerations.

Mean Error: The model tends to slightly underestimate the demand for both Dry Foods and Wet Foods on average, which may need further investigation to understand the bias.

Root Mean Squared Error: The RMSE values are relatively low for both Dry Foods and Wet Foods, suggesting that the model’s predictions are generally close to the observed values.

Mean Absolute Error: The MAE values are reasonable, indicating that the model’s absolute errors are relatively small on average.

Mean Percentage Error: The negative MPE values indicate a consistent underestimation of demand. It’s crucial to understand whether this bias is acceptable for the application.

Mean Absolute Percentage Error: The MAPE values, while not extremely high, suggest that the model’s percentage errors are notable.

Mean Absolute Scaled Error: Both MASE values are below 1, indicating that the model outperforms a naive forecast, but there is room for improvement.

The MAPE values for both models indicate favorable accuracy, translating to an effective prediction accuracy of approximately 77.8% for Dry Foods and 75.7% for Wet Foods when subtracted from 100%. This implies that the models’ forecasts are, on average, within a 22.20% margin of error for Dry Foods and a 24.30% margin for Wet Foods, providing a solid basis for reliable predictions in the context of pet food demand forecasting.Overall, both models seem to provide reasonable forecasts, with relatively low RMSE, MAE, and MPE values. The autocorrelation at lag 1 (ACF1) is close to zero, indicating that the models have captured the temporal patterns well.

Prediction Performance

Forecasting

From the dataset 2022 to 2023 was reserved specifically for evaluating the predictive performance of each model by assessing their accuracy. Utilizing the forecast function from the forecast package, the models generated predictions for the next 12 months, forecasting both Dry Foods and Wet Foods demand.

Each graph includes the actual test data in orange, the mean of the prediction in blue, an 80% prediction interval represented by a deep purple shaded area, and a 95% prediction interval displayed as a light purple shaded area. These visualizations provide a comprehensive overview of the model’s forecasting capabilities and their alignment with the actual test data.

Forecasting from Original Data

Log transformation is a common technique used in time series forecasting to stabilize variance and make the patterns in the data more apparent. When the log-transformed predictions closely track the original data, it suggests that the forecasting model is capturing the underlying patterns effectively. The comparison between the blue log-transformed prediction line and the orange original data line is a visual way to assess the accuracy and alignment of the forecasted values with the actual observations

In the context of time series forecasting, the statement suggests that after applying a log transformation to the forecasted data for both wet foods and dry foods, the resulting prediction line in blue closely follows the actual line in orange. This indicates that the log-transformed predictions align well with the actual values from the original data.

Data Transformation and MySQL Integration

After finishing the forecasting process, moving the data to a MySQL database and running specific queries become really important. This helps a lot in making smart decisions for planning and allocating resources strategically. This step allows us to merge the forecasted data into a well-organized database. It creates a central place for information, making it easier to manage and access. This approach not only improves how we access information but also helps in maintaining the database efficiently, making decision support systems work better.

MySQL Database and Query

MySQL is an open-source relational database management system that is widely used for managing and organizing structured data MySQL Development Team (n.d.). It is one of the most popular databases and is commonly used for various applications, ranging from small-scale websites to large enterprise systems.

MySQL will act as a reliable and scalable backend database for this project, by providing essential capabilities for efficiently storing, organizing, querying, and integrating data. Below I am going to provide some example llustrating how specific answers can be obtained through SQL queries.

  • Identifying Underserved Zip Code Areas:

By analyzing the data, the organization can pinpoint zip code areas that are underserved in terms of pet food demand. This information is valuable for directing outreach efforts and ensuring that resources are allocated to areas with the greatest need.

  • Analyzing Foods Demand by Pet Type and Distribution Areas:

The data analysis allows for a detailed examination of pet food demand categorized by pet type. This insight helps the organization understand the varying needs of different types of pets and strategically plan food distribution in specific areas.

  • Identifying Highest Need Areas by Number of Pets:

The data will reveal areas with the highest concentration of pets, indicating regions where the demand for pet food is particularly high. This knowledge is essential for prioritizing efforts and resources to address the needs of communities with a larger number of pets. In summary, the outcomes of this analysis will provide a comprehensive view of the organization’s operational landscape, enabling targeted interventions and strategic decisions to address specific needs in different areas.

In summary, the outcomes of this analysis will provide a comprehensive view of the organization’s operational landscape, enabling targeted interventions and strategic decisions to address specific needs in different areas.

Limitations

The precision of the forecasting models relies significantly on the quality of the input data. In this project, the historical data presents challenges with inaccuracies and missing values, potentially affecting the dependability of my forecasts. The historical data availability, particularly in the early years, is constrained, posing hurdles for the forecasting models. Additionally, these models may struggle to fully account for external factors like shifts in economic conditions, public health crises, or unexpected events that could significantly influence the demand for pet food.

Future Research Areas

implementing the storage and retrieval of data in a MySQL database involves creating tables with unique identifiers for customers and order details. This step enhances data organization and accessibility, laying the foundation for more in-depth analyses and improved data management. Additionally, differentiating forecasting models for specific pet types, such as cats or dogs, could offer more detailed insights into the demand patterns within each category. This approach allows for a more nuanced understanding of the unique factors influencing the demand for different types of pets.

Conclusions

This project has been a dynamic journey, navigating the intricacies of data analysis, modeling, and decision-making. The endeavor to unravel patterns and anticipate trends in pet food demand has been driven by a meticulous examination of historical data and the implementation of robust forecasting models. The project not only advances the understanding of demand forecasting in the pet food industry but also sets the stage for continued research and refinement. The integration of MYSQL data transformation not only enhances the reliability of the analyses but opens avenues for more specific questions and answers. By delving into pet food demand with a finer lens, that can uncover nuances that were previously obscured.

This project will empower the organization to adeptly comprehend and oversee its pet food bank. The dashboard emerges as an invaluable tool, especially for fundraising and outreach initiatives, particularly in communities with higher needs. Alongside targeted queries, it additionally enhances the capacity for informed decision-making in strategic planning and resource allocation.

Bibliography

Alshobaili, Fahdah A, and Nada A AlYousefi. 2019. “The Effect of Smartphone Usage at Bedtime on Sleep Quality Among Saudi Non-Medical Staff at King Saud University Medical City.” Journal of Family Medicine and Primary Care 8 (6): 1953.
Boehm, Julia K., Theresa Bowers, Joshua Kees, Chelsea Kozikowski, James W. Dearing, Teresia O’Connor, and Lee M. Ritterband. 2014. “Promoting Patient Engagement with Virtual Avatars: A Novel Computer-Based Intervention to Overcome Spatial and Temporal Barriers to Chronic Pain Rehabilitation.” Journal of Medical Internet Research 16 (1). https://doi.org/10.2196/jmir.2947.
Chatfield, Chris. 2000. Time-Series Forecasting. CRC press.
Devore, Jay L. 2015. Probability and Statistics for Engineering and the Sciences. Cengage Learning.
Grimaldi-Puyana, Moisés, José Marı́a Fernández-Batanero, Curtis Fennell, and Borja Sañudo. 2020. “Associations of Objectively-Assessed Smartphone Use with Physical Activity, Sedentary Behavior, Mood, and Sleep Quality in Young Adults: A Cross-Sectional Study.” International Journal of Environmental Research and Public Health 17 (10): 3499.
MySQL Development Team. n.d. “MySQL.” https://www.mysql.com/.
Rubi, Maksuda Akter, Hasan Imam Bijoy, and Abu Kowshir Bitto. 2021. “Life Expectancy Prediction Based on GDP and Population Size of Bangladesh Using Multiple Linear Regression and ANN Model.” In 2021 12th International Conference on Computing Communication and Networking Technologies (ICCCNT), 1–6. https://doi.org/10.1109/ICCCNT51525.2021.9579594.
Wikipedia contributors. 2023a. “Gradient Boosting — Wikipedia, the Free Encyclopedia.” https://en.wikipedia.org/w/index.php?title=Gradient_boosting&oldid=1177258913.
———. 2023b. “Random Forest — Wikipedia, the Free Encyclopedia.” https://en.wikipedia.org/w/index.php?title=Random_forest&oldid=1186786280.
LS0tCnRpdGxlOiAiXFx2c3BhY2V7LTJjbX0gKionQ2Fwc3RvbmUgUG9ydGZvbGlvIFByb2plY3QnKioiCmF1dGhvcjogIlNoYW1pbWEgSGFxdWUiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jLXRpdGxlOiBDdXN0b20gVE9DIFRpdGxlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jLXRpdGxlOiBDdXN0b20gVE9DIFRpdGxlCiAgICBlcnJvcjogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKY29kZV9mb2xkaW5nOiBoaWRlCmJpYmxpb2dyYXBoeToKLSBSZWZlcmFuY2VzLmJpYgotIFJGTC5iaWIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQodGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSA2MCksIHRpZHkgPSBUUlVFKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShhc3RzYSkKbGlicmFyeShkYXRhc2V0cykKbGlicmFyeShUU0EpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkodHNlcmllcykKbGlicmFyeShrbml0cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh6b28pCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHRzZXJpZXMpCnRoZW1lX3NldCh0aGVtZV9idygpKQpsaWJyYXJ5KGZvcmVjYXN0KQpgYGAKClxuZXdwYWdlCgojIEFic3RyYWN0CgpUaGlzIGNhcHN0b25lIHBvcnRmb2xpbyBpbmNsdWRlcyB0aHJlZSBzaWduaWZpY2FudCBkYXRhIGFuYWx5dGljcyBwcm9qZWN0cywgZWFjaCBjb250cmlidXRpbmcgdmFsdWFibGUgaW5zaWdodHMgdG8gZGl2ZXJzZSBkb21haW5zLiBUaGUgaW5pdGlhbCBwcm9qZWN0IGV4cGxvcmVzICoqIlRoZSBJbXBhY3Qgb2YgU21hcnRwaG9uZSBVc2FnZSBCZWZvcmUgQmVkdGltZSBvbiBTbGVlcCBRdWFsaXR5IEFtb25nIEFkdWx0cyIqKiwgaW50ZW5kaW5nIHRvIHVuY292ZXIgdGhlIGludHJpY2F0ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzbWFydHBob25lIGhhYml0cyBhbmQgc2xlZXAgcXVhbGl0eS4gVXRpbGl6aW5nIGEgc2FtcGxlIHN1cnZleSBhbmQgc3RhdGlzdGljYWwgYW5hbHlzZXMsIHRoaXMgc3R1ZHkgc2hlZHMgbGlnaHQgb24gdGhlIHBvdGVudGlhbCBlZmZlY3RzIG9mIHByZS1zbGVlcCBzbWFydHBob25lIHVzZSwgaG9sZGluZyBpbXBsaWNhdGlvbnMgZm9yIHByb21vdGluZyBoZWFsdGhpZXIgc2xlZXAgaGFiaXRzIGFtb25nIGFkdWx0cy4KCgpUaGUgc2Vjb25kIHZlbnR1cmUsICoqIkV4cGxvcmluZyB0aGUgQ29ycmVsYXRpb24gQmV0d2VlbiBMaWZlIEV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgQ2FwaXRhIFRocm91Z2ggTWFjaGluZSBMZWFybmluZyBNb2RlbHMiKiouIEluIHRoaXMgcHJvamVjdCwgSSBleHBsb3JlZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyB0aHJvdWdoIGh5cG90aGVzaXMgdGVzdGluZyBhbmQgcHJlc2VudGVkIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXguICBJIGVtcGxveWVkIExpbmVhciBSZWdyZXNzaW9uIGFuZCBSYW5kb20gRm9yZXN0IG1vZGVscy4gQWRkaXRpb25hbGx5LCBJIGNvbXBhcmVkIHRoZWlyIHBlcmZvcm1hbmNlIHdpdGggU3VwcG9ydCBWZWN0b3IgTWFjaGluZSBhbmQgR3JhZGllbnQgQm9vc3RpbmcgbW9kZWxzIHRvIGRldGVybWluZSB0aGUgbW9zdCBlZmZlY3RpdmUgcHJlZGljdGl2ZSBtb2RlbC4gVGhpcyBhbmFseXNpcyBwcm92aWRlcyBhY3Rpb25hYmxlIGluc2lnaHRzIGZvciBwb2xpY3kgZGVjaXNpb25zLCBlY29ub21pYyBzdHJhdGVnaWVzLCBhbmQgaGVhbHRoY2FyZSBpbnZlc3RtZW50cy4gTGV2ZXJhZ2luZyBhZHZhbmNlZCBhbmFseXRpY3MgYW5kIGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlLCB0aGUgcHJvamVjdCB1bnZlaWxzIGlubm92YXRpdmUgcGVyc3BlY3RpdmVzLCBpbmZsdWVuY2luZyBpbnRlcnZlbnRpb25zIHRvIGVuaGFuY2UgdGhlIHF1YWxpdHkgb2YgbGlmZSBhbmQgZXh0ZW5kIGxpZmUgZXhwZWN0YW5jeSBvbiBhIGdsb2JhbCBzY2FsZS4KCgoKVGhlIHRoaXJkIHByb2plY3QsICoqIkZvcmVjYXN0aW5nIG9mIFBldCBGb29kcyBEZW1hbmQgIFVzaW5nIFRpbWUgU2VyaWVzIEFuYWx5c2lzIHRvIEVuaGFuY2UgU3RyYXRlZ2ljIFRlY2huaXF1ZXMgYW5kIFJlc291cmNlIEFsbG9jYXRpb24gZm9yIGEgTm9uLXByb2ZpdCBPcmdhbml6YXRpb24iKiosIHNob3djYXNlcyBhIGNlbnRyYWwgZGFzaGJvYXJkIGZvciB0aGUgbm9uLXByb2ZpdCBvcmdhbml6YXRpb24gRnJpZW5kcyBmb3IgTGlmZS4gQnkgcHJvY2Vzc2luZyBhbmQgdmlzdWFsaXppbmcgbmV3bHkgYWNxdWlyZWQgZGF0YSwgdGhlIGRhc2hib2FyZCBoZWxwcyBpbiBmdW5kcmFpc2luZyBhbmQgb3V0cmVhY2ggZWZmb3J0cyBpbiBoaWdoZXItbmVlZCBjb21tdW5pdGllcy4gVGhyb3VnaCB0aW1lIHNlcmllcyBhbmFseXNpcyB0ZWNobmlxdWVzIGZvcmVjYXN0cyBmb3IgbW9udGhseSBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkZW1hbmQsIGRlcml2ZWQgdGhlIG9yZ2FuaXphdGlvbiB0byB1bmRlcnN0YW5kIGFuZCBtYW5hZ2UgaXRzIHBldCBmb29kIGJhbmsgZWZmaWNpZW50bHkuIFRoZSB0cmFuc2ZlciBvZiBkYXRhIHRvIGEgTXlTUUwgZGF0YWJhc2UsIGNvdXBsZWQgd2l0aCB0YXJnZXRlZCBxdWVyaWVzLCBmdXJ0aGVyIGZhY2lsaXRhdGVzIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbm5pbmcgYW5kIHJlc291cmNlIGFsbG9jYXRpb24uCgoKVGhlc2UgcHJvamVjdHMgY29sbGVjdGl2ZWx5IHNob3djYXNlIGEgcmFuZ2Ugb2YgYW5hbHl0aWNhbCBza2lsbHMsIGZyb20gaW52ZXN0aWdhdGluZyByZWxhdGlvbnNoaXBzIGFuZCBwcm92aWRpbmcgYWN0aW9uYWJsZSBpbnNpZ2h0cyB0byBzdXBwb3J0aW5nIG5vbi1wcm9maXQgb3JnYW5pemF0aW9ucyB0aHJvdWdoIGVmZmVjdGl2ZSBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIGZvcmVjYXN0aW5nLiBUaGUgbWV0aG9kb2xvZ2llcyBlbXBsb3llZCBhaW0gdG8gY29udHJpYnV0ZSB2YWx1YWJsZSBrbm93bGVkZ2UgYW5kIHN1cHBvcnQgZGVjaXNpb24tbWFraW5nIGluIGRpdmVyc2UgZG9tYWlucy4KCgpcbmV3cGFnZQoKIyAqKlRoZSBJbXBhY3Qgb2YgU21hcnRwaG9uZSBVc2FnZSBCZWZvcmUgQmVkdGltZSBvbiBTbGVlcCBRdWFsaXR5IEFtb25nIEFkdWx0cyoqCgoKCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI5MCUifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9TY3JlZW4gU2hvdCAyMDIzLTA5LTE1IGF0IDkuNDUuMTIgQU0ucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAojIEludHJvZHVjdGlvbi9CYWNrZ3JvdW5kCgpUaGUgd2lkZXNwcmVhZCBhZG9wdGlvbiBvZiBzbWFydHBob25lcyBoYXMgcmVhY2hlZCBhIGdsb2JhbCBzY2FsZSBpbiByZWNlbnQgeWVhcnMuIEFzIG9mIGVhcmx5IDIwMjEsIHRoZSBnbG9iYWwgc21hcnRwaG9uZSB1c2VyIGNvdW50IHJlYWNoZWQgMy44IGJpbGxpb24sIHNpZ25pZnlpbmcgdGhhdCBhcHByb3hpbWF0ZWx5IDQ4LjUzJSBvZiB0aGUgd29ybGQncyBwb3B1bGF0aW9uIG5vdyBwb3NzZXNzZXMgYSBzbWFydHBob25lLiBJbiB0aGUgVW5pdGVkIFN0YXRlcywgNzclIG9mIGFkdWx0cyBvd24gc21hcnRwaG9uZXMuIFNtYXJ0cGhvbmVzIGhhdmUgdHJhbnNpdGlvbmVkIGZyb20gYmVpbmcgbWVyZSBnYWRnZXRzIHRvIGJlY29taW5nIGRhaWx5IGVzc2VudGlhbHMgZm9yIG1vc3QgcGVvcGxlIGR1ZSB0byB0aGVpciBjb252ZW5pZW5jZSBpbiBhY2Nlc3NpbmcgaW5mb3JtYXRpb24sIGZhY2lsaXRhdGluZyBzb2NpYWwgY29ubmVjdGlvbnMsIGFpZGluZyB3b3JrcGxhY2UgdGFza3MsIGFuZCBwcm92aWRpbmcgZW50ZXJ0YWlubWVudCBvcHRpb25zLiBTbWFydHBob25lcyBoYXZlIGFzc3VtZWQgYSBwaXZvdGFsIHJvbGUgaW4gdGhlIHJlYWxtIG9mIG1lZGljYWwgaGVhbHRoLCBvZmZlcmluZyBzdWJzdGFudGlhbCBiZW5lZml0cyB0byBib3RoIHBhdGllbnRzIGFuZCBoZWFsdGhjYXJlIHByb2Zlc3Npb25hbHMgQGdyaW1hbGRpMjAyMGFzc29jaWF0aW9ucy4gSG93ZXZlciwgYWxvbmdzaWRlIHRoZWlyIG51bWVyb3VzIGFkdmFudGFnZXMsIGNvbmNlcm5zIGhhdmUgYXJpc2VuIHJlZ2FyZGluZyB0aGUgcGh5c2ljYWwgYW5kIHBzeWNob2xvZ2ljYWwgaW1wbGljYXRpb25zIGFzc29jaWF0ZWQgd2l0aCBwcm9ibGVtYXRpYyBzbWFydHBob25lIHVzZSwgcm91Z2hseSA2OCBwZXJjZW50IG9mIHRoZSBzbWFydHBob25lIHVzZXJzIGtlcHQgdGhlaXIgZGV2aWNlcyBvbiB0aGVpciBiZWRzaWRlIHRhYmxlcyBkdXJpbmcgc2xlZXAuIEFsdGhvdWdoIHNjcmVlbiB0aW1lIHZhcmllZCBhbW9uZyBkaWZmZXJlbnQgYWdlIGdyb3VwcyBhbmQgcmFjaWFsIGJhY2tncm91bmRzLCBpdCB3YXMgZmFpcmx5IGNvbnNpc3RlbnQgYWNyb3NzIHZhcmlvdXMgc29jaW9lY29ub21pYyBsZXZlbHMuIFRoZSBleHRlbnQgb2Ygc21hcnRwaG9uZSB1c2FnZSBoYXMgYSBkaXJlY3QgbGluayB0byBzbGVlcCBwYXR0ZXJucywgYXMgcGVyIGEgc3R1ZHkgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIGF0IFVDIFNhbiBGcmFuY2lzY28uIFRoZXkgZm91bmQgYSBub3Rld29ydGh5IGNvbm5lY3Rpb24gYmV0d2VlbiBpbmNyZWFzZWQgc21hcnRwaG9uZSB1c2FnZSBhbmQgdHdvIGtleSBmYWN0b3JzOiBzaG9ydGVyIHNsZWVwIGR1cmF0aW9uIGFuZCBwb29yZXIgc2xlZXAgZWZmaWNpZW5jeS5bMV0oaHR0cHM6Ly93d3cudWNzZi5lZHUvbmV3cy8yMDE2LzExLzQwNDg4Ni9zbWFydHBob25lLXVzZS1pbmNyZWFzZXMtc28tZG9lcy1sYWNrLXNsZWVwKQoKCgoKIyMgUHJvYmxlbSBTdGF0ZW1lbnQKClVuZGVyc3RhbmRpbmcgdGhlIGNvbnRleHQgYW5kIG1vdGl2YXRpb24gdG8gaWRlbnRpZnlpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNtYXJ0cGhvbmUgdXNhZ2UgYW5kIHNsZWVwIHF1YWxpdHkgYW1vbmcgYWR1bHRzLgpUaGlzIHJlc2VhcmNoIHByb2plY3QgYWltcyB0byBpbnZlc3RpZ2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBhbmQgc2xlZXAgcXVhbGl0eSBhbW9uZyBhZHVsdHMuIFRoZSBzdHVkeSB3aWxsIHV0aWxpemUgYSBzYW1wbGUgc3VydmV5IHRvIGNvbGxlY3QgZGF0YSBvbiBwYXJ0aWNpcGFudHMnIHNtYXJ0cGhvbmUgdXNhZ2UgaGFiaXRzIGJlZm9yZSBiZWR0aW1lIGFuZCB0aGVpciBzbGVlcCBxdWFsaXR5LiBEZW1vZ3JhcGhpYyBpbmZvcm1hdGlvbiB3aWxsIGFsc28gYmUgZ2F0aGVyZWQgdG8gZXhhbWluZSBwb3RlbnRpYWwgdmFyaWF0aW9ucyBpbiB0aGUgcmVsYXRpb25zaGlwLiBTdGF0aXN0aWNhbCBhbmFseXNlcyB3aWxsIGJlIGNvbmR1Y3RlZCB0byBkZXRlcm1pbmUgdGhlIGV4dGVudCBvZiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBzbWFydHBob25lIHVzYWdlIGJlZm9yZSBiZWR0aW1lIGFuZCBzbGVlcCBxdWFsaXR5LiBUaGUgZmluZGluZ3Mgb2YgdGhpcyBzdHVkeSB3aWxsIGNvbnRyaWJ1dGUgdG8gb3VyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGVmZmVjdHMgb2Ygc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBvbiBzbGVlcCBwYXR0ZXJucyBhbmQgbWF5IGhhdmUgaW1wbGljYXRpb25zIGZvciBwcm9tb3RpbmcgaGVhbHRoeSBzbGVlcCBoYWJpdHMgYW1vbmcgYWR1bHRzLgoKIyBNZXRob2QKClRoaXMgcmVzZWFyY2ggaXMgZGVzaWduIGJ5IGEgKipjcm9zcy1zZWN0aW9uYWwgc3R1ZHkqKi5UaGUgZGF0YSB3YXMgY29sbGVjdGVkIGZyb20gYSBkaXZlcnNlIGdyb3VwIG9mIGFkdWx0cyBpbiB0aGUgVVNBLCByZWdhcmRsZXNzIG9mIGFnZSwgZ2VuZGVyLCBwcm9mZXNzaW9uIGFueSBvdGhlciBkZW1vZ3JhcGhpYyBmYWN0b3JzLiBUaGUgcXVlc3Rpb25zIHdhcyBkaXN0cmlidXRlZCByYW5kb21seSB0byAyNSBhZHVsdHMsIGVhY2ggb2Ygd2hvbSB3YXMgcHJlc2VudGVkIHdpdGggOCBxdWVzdGlvbnMuIDEwIHdlcmUgZXhjbHVkZWQgb25seSAxNSBwYXJ0aWNpcGFudHMgcmVzcG9uZGVkIHRvIGV2ZXJ5IHNpbmdsZSBxdWVzdGlvbi5QYXJ0aWNpcGFudHMgd2VyZSByZWFzc3VyZWQgdGhhdCB0aGVpciByZXNwb25zZSB0byBvdXIgcXVlc3Rpb25uYWlyZSBpcyBzdHJpY3RseSBjb25maWRlbnRpYWwuIFJlc3BvbmRlZCB3ZXJlIHJlYXNzdXJlZCB0aGF0IHRoZWlyIHBhcnRpY2lwYXRpb24gd2lsbCBiZSBjb25maWRlbnRpYWwgQGFsc2hvYmFpbGkyMDE5ZWZmZWN0LgoKIyMgU3VydmV5IFF1ZXN0aW9ubmFpcmUKClRoZSBwYXJ0aWNpcGFudHMgd2VyZSBhc2tlZCA4IHF1ZXN0aW9ucy5UaGUgZmlyc3QgcXVlc3Rpb24gd2FzIGhvdyBmcmVxdWVudGx5IGRvIHRoZXkgdXNlIGEgc21hcnRwaG9uZSBiZWZvcmUgZ29pbmcgdG8gYmVkOkV2ZXJ5IG5pZ2h0LFNldmVyYWwgdGltZXMgYSB3ZWVrLCBPY2Nhc2lvbmFsbHksIFJhcmVseSwgTmV2ZXIuU2Vjb25kIHF1ZXN0aW9uIHdhcyBPbiBhdmVyYWdlIGhvdyBtYW55IG1pbnV0ZXMgdGhleSBzcGVuZCB1c2luZyB0aGVpciBzbWFydHBob25lIGJlZm9yZSBiZWR0aW1lOiBMZXNzIHRoYW4gMTUgbWludXRlcywgMTUtMzAgbWludXRlcywgMzAtNjAgbWludXRlcywgTW9yZSB0aGFuIDYwIG1pbnV0ZXMuVGhpcmQgcXVlc3Rpb24gd2FzLFdoYXQgYWN0aXZpdGllcyBkbyB0aGV5IHVzdWFsbHkgZW5nYWdlIGluIG9uIHRoZWlyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZDogU29jaWFsIG1lZGlhIGJyb3dzaW5nLCBXYXRjaGluZyB2aWRlb3MvbW92aWVzLCB0ZXh0aW5nL21lc3NhZ2luZywgUmVhZGluZyBhcnRpY2xlcy9lLWJvb2tzLCBQbGF5aW5nIGdhbWVzLE90aGVyIChwbGVhc2Ugc3BlY2lmeSkuIFRoZSBmb3VydGggcXVlc3Rpb24gd2FzLCBob3cgZnJlcXVlbnRseSBkbyB0aGV5IGV4cGVyaWVuY2UgZGlmZmljdWx0eSBmYWxsaW5nIGFzbGVlcCBhZnRlciB1c2luZyB0aGVpciBzbWFydHBob25lIGJlZm9yZSBiZWR0aW1lOiBWZXJ5IGZyZXF1ZW50bHksIEZyZXF1ZW50bHksIE9jY2FzaW9uYWxseSwgUmFyZWx5LCBOZXZlci4gT24gYSBzY2FsZSBvZiAxLTEwLCByYXRlIHRoZSBxdWFsaXR5IG9mIHNsZWVwIG9uIG5pZ2h0cyB3aGVuIHRoZXkgdXNlIHRoZWlyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZC4gKDEgLSBWZXJ5IHBvb3IsIDEwIC0gRXhjZWxsZW50KSBPbiBhIHNjYWxlIG9mIDEtMTAsIHJhdGUgdGhlIHF1YWxpdHkgb2YgeW91ciBzbGVlcCBvbiBuaWdodHMgd2hlbiB5b3UgZG8gbm90IHVzZSB5b3VyIHNtYXJ0cGhvbmUgYmVmb3JlIGdvaW5nIHRvIGJlZC4gKDEgLSBWZXJ5IHBvb3IsIDEwIC0gRXhjZWxsZW50KS4gRmlmdGggcXVlc3Rpb24gd2FzLCBoYXZlIHRoZXkgbm90aWNlZCBhbnkgb2YgdGhlIGZvbGxvd2luZyBzbGVlcCBkaXN0dXJiYW5jZXMgYWZ0ZXIgdXNpbmcgdGhlaXIgc21hcnRwaG9uZSBiZWZvcmUgYmVkdGltZT8gKFNlbGVjdCBhbGwgdGhhdCBhcHBseSk6IERpZmZpY3VsdHkgZmFsbGluZyBhc2xlZXAsIEZyZXF1ZW50IGF3YWtlbmluZ3MgZHVyaW5nIHRoZSBuaWdodCwgUmVzdGxlc3Mgc2xlZXAsIEVhcmx5IGF3YWtlbmluZywgTmlnaHRtYXJlcywgTm9uZSBvZiB0aGUgYWJvdmUuIFNpeHRoIHF1ZXN0aW9uIHdhcywgYXJlIHRoZXkgYXdhcmUgb2YgdGhlIHBvdGVudGlhbCBuZWdhdGl2ZSBlZmZlY3RzIG9mIHNtYXJ0cGhvbmUgdXNhZ2UgYmVmb3JlIGJlZHRpbWUgb24gc2xlZXAgcXVhbGl0eTogWWVzL05vLiBTZXZlbnRoIHF1ZXN0aW9uIHdhcywgaGF2ZSB0aGV5IHRyaWVkIGFueSBzdHJhdGVnaWVzIHRvIGxpbWl0IG9yIHJlZHVjZSBzbWFydHBob25lIHVzYWdlIGJlZm9yZSBiZWR0aW1lPyAoU2VsZWN0IGFsbCB0aGF0IGFwcGx5KTogU2V0dGluZyBkZXZpY2UgdXNhZ2UgbGltaXRzLCBVc2luZyBibHVlIGxpZ2h0IGZpbHRlcnMsIEtlZXBpbmcgdGhlIHNtYXJ0cGhvbmUgb3V0IG9mIHRoZSBiZWRyb29tLCBFbmdhZ2luZyBpbiByZWxheGluZyBhY3Rpdml0aWVzIGJlZm9yZSBiZWQsIE5vbmUgb2YgdGhlIGFib3ZlLiBBbmQgdGhlIGZpbmFsIGFuZCBsYXN0IHF1ZXN0aW9uIHdhcywgaG93IHdvdWxkIHRoZXkgcmF0ZSB0aGVpciBvdmVyYWxsIHNhdGlzZmFjdGlvbiB3aXRoIHRoZWlyIHNsZWVwIHF1YWxpdHk6VmVyeSBkaXNzYXRpc2ZpZWQsIERpc3NhdGlzZmllZCwgTmV1dHJhbCwgU2F0aXNmaWVkLiBWZXJ5IHNhdGlzZmllZAoKIyBTdGF0aXN0aWNhbCBNZXRob2RzCgpCeSBVc2luZyAqKnR3by10YWlsZWQgdC10ZXN0KiosIHdlIGFyZSB0ZXN0aW5nIHdoZXRoZXIgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW5zIG9mIHRoZSB0d28gZ3JvdXBzIFNsZWVwIFF1YWxpdHkgKHdpdGggU21hcnRwaG9uZSkgYW5kIFNsZWVwIFF1YWxpdHkgKHdpdGhvdXQgU21hcnRwaG9uZSksIGJ1dCB3ZSBkbyBub3Qgc3BlY2lmeSB0aGUgZGlyZWN0aW9uIG9mIHRoZSBkaWZmZXJlbmNlICh3aGV0aGVyIG9uZSBpcyBncmVhdGVyIG9yIHNtYWxsZXIgdGhhbiB0aGUgb3RoZXIpLiBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoJEhfYSQpIGlzIHR3by1zaWRlZCwgaW5kaWNhdGluZyB0aGF0IHRoZSBtZWFucyBhcmUgbm90IGVxdWFsLgoKV2UgY2FuIHBlcmZvcm0gdGhpcyB0d28tdGFpbGVkIHQtdGVzdCBpbiBSIHVzaW5nIHRoZSBgdC50ZXN0KClgIGZ1bmN0aW9uLCB0aGUgYGFsdGVybmF0aXZlYCBhcmd1bWVudCBmb3IgdGhlIHR3by10YWlsZWQgdGVzdCBpcyBiZWxvdy4gJCQKXGJlZ2lue2FsaWduKn0KJiBcdGV4dHtIfV8wOiBcbXVfMSA9IFxtdV8yIFxxdWFkIApcXAomIFx0ZXh0e0h9X2E6IFxtdV8xIFxuZXEgXG11XzIgXHF1YWQgIFxcClxlbmR7YWxpZ24qfQokJCAkJApcdGV4dHtXaGVyZTp9XFwKXCBcbXVfMSA9IE1lYW5cIFNsZWVwXCBRdWFsaXR5XCAod2l0aFwgU21hcnRwaG9uZSkgXFwgClxtdV8yID0gTWVhbiBcIFNsZWVwXCBRdWFsaXR5XCAod2l0aG91dFwgU21hcnRwaG9uZSkKJCQKCiMjIEZvcm11bGEgb2YgVHdvIFRhaWxlZCB0LXRlc3QKCiQkIAp0ID0gXGZyYWN7e1xiYXJ7eH1fMSAtIFxiYXJ7eH1fMn19e3tzX3AgXHNxcnR7XGZyYWN7MX17e25fMX19ICsgXGZyYWN7MX17e25fMn19fX19CiQkICQkIFwgClx0ZXh0e0RlZ3JlZXMgb2YgRnJlZWRvbSAoZGYpfSA9IG5fMSArIG5fMiAtIDIKXCAkJAoKJCQgXApcYWxwaGEgPSAxIC0gXHRleHR7Q29uZmlkZW5jZSBMZXZlbH0KXCAkJAoKJCRcCnRfe1x0ZXh0e2NyaXR9fSA9IFx0ZXh0e2NyaXRpY2FsIHZhbHVlIGZyb20gdC10YWJsZSBvciBjYWxjdWxhdG9yIGF0IGRmIGRlZ3JlZXMgb2YgZnJlZWRvbSBhbmR9IFwgXGZyYWN7XGFscGhhfXsyfSBcIFx0ZXh0e3NpZ25pZmljYW5jZSBsZXZlbCAoZm9yIGEgdHdvLXRhaWxlZCB0ZXN0KX0KXCAkJAoKJCRcClx0ZXh0e0lmfSBcIHx0fCA+IHRfe1x0ZXh0e2NyaXR9fSwgXCBcdGV4dHtyZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy59ClwgJCQKCiQkXApcdGV4dHtPdGhlcndpc2UsIGZhaWwgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMufQpcICQkCgpUaGlzIGZvcm11bGEgcmVwcmVzZW50cyB0aGUga2V5IGNvbXBvbmVudHMgb2YgYSB0d28tdGFpbGVkIHQtdGVzdCBpbmNsdWRpbmcgdGhlIHQtc3RhdGlzdGljIGNhbGN1bGF0aW9uLCBkZWdyZWVzIG9mIGZyZWVkb20gKGRmKSwgc2lnbmlmaWNhbmNlIGxldmVsIChhbHBoYSksIGNyaXRpY2FsIHZhbHVlICh0X2NyaXQpLCBhbmQgdGhlIGRlY2lzaW9uIHJ1bGUgZm9yIGh5cG90aGVzaXMgdGVzdGluZyBAZGV2b3JlMjAxNXByb2JhYmlsaXR5LgpcbmV3cGFnZQoKCmBgYHtyLCBlY2hvID0gRkFMU0UscmVzdWx0cz0naGlkZSd9CmRhdGEgPC0gcmVhZC5jc3YoInN1cnZleWRhdGEuY3N2IikKCiMgQ3JlYXRlIGEgc2FtcGxlIGRhdGFzZXQKc2V0LnNlZWQoMTIzKQpzYW1wbGVfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFJlc3BvbmRlbnQgPSAxOjE1LAogIFNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lID0gcm5vcm0oMTUsIG1lYW4gPSA2LCBzZCA9IDEpLAogIFNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lID0gcm5vcm0oMTUsIG1lYW4gPSA4LCBzZCA9IDEpCikKCmBgYAoKIyMgU3VtbWFyeSBTdGF0aXN0aWNzCgpgYGB7ciwgZWNobyA9IEZBTFNFfQojIENhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5KHNhbXBsZV9kYXRhW2MoIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIiwgIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIildKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzCnN1bW1hcnlfdGFibGUgPC0gZGF0YS5mcmFtZSgKICBNZWFzdXJlID0gcm93bmFtZXMoc3VtbWFyeV9zdGF0cyksCiAgV2l0aF9TbWFydHBob25lID0gc3VtbWFyeV9zdGF0c1ssIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIl0sCiAgV2l0aG91dF9TbWFydHBob25lID0gc3VtbWFyeV9zdGF0c1ssIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIl0KKQoKIyBQcmludCB0aGUgc3VtbWFyeSB0YWJsZQpwcmludChzdW1tYXJ5X3RhYmxlKQoKCgpgYGAKSXQgYXBwZWFycyB0aGF0IHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciB0d28gZGlmZmVyZW50IHZhcmlhYmxlcyAiV2l0aF9TbWFydHBob25lIiBhbmQgIldpdGhvdXRfU21hcnRwaG9uZSIsIHdoaWNoIHJlcHJlc2VudCBzb21lIG1lYXN1cmUgcmVsYXRlZCB0byBzbGVlcCBxdWFsaXR5LiBXaXRoIHNtYXJ0cGhvbmUgYmVmb3JlIGJlZHRpbWUgdGhlIG1pbmltdW0gNC43NSBhbmQgbWF4aW11bSBpcyA3LjcuIFNpbWlsYXJ5LCB3aXRob3V0IHNtYXJ0cGhvbmUgdGhlIG1pbmltdW0gaXMgNi4wMzMgYW5kIHRoZSBtYXhpbXVtIGlzIDkuNzg3LiBUaGlzICoqc3VtbWFyeSBzdGF0aXN0aWNzKiogYWxsb3dpbmcgdXMgdG8gY29tcGFyZSB0aGUgY2VudHJhbCB0ZW5kZW5jeSAobWVhbiBhbmQgbWVkaWFuKSBhbmQgdGhlIHNwcmVhZCAobWluaW11bSwgbWF4aW11bSwgYW5kIHF1YXJ0aWxlcykgb2Ygd2l0aCBzbWFydHBob25lIGFuZCB3aXRob3V0IHNtYXJ0cGhvbmUgaW4gdGhlIGNvbnRleHQgb2YgdGhpcyByZXNlYXJjaCBzdHVkeS4gRm9yIGV4YW1wbGUsIHdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBzbGVlcCBxdWFsaXR5IGFwcGVhcnMgdG8gYmUgbG93ZXIgd2hlbiBpbmRpdmlkdWFscyB1c2Ugc21hcnRwaG9uZXMgYmVmb3JlIGJlZHRpbWUgY29tcGFyZWQgdG8gd2hlbiB0aGV5IGRvIG5vdCB1c2Ugc21hcnRwaG9uZXMuIEZ1cnRoZXIgc3RhdGlzdGljYWwgdGVzdHMgbWF5IGhlbHAgdXMgdG8gZGV0ZXJtaW5lIGlmIHRoaXMgZGlmZmVyZW5jZSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKIyMgQm94LVBsb3QKCmBgYHtyLCBlY2hvID0gRkFMU0UscmVzdWx0cz0naGlkZSd9Cgpib3hwbG90KAogIHNhbXBsZV9kYXRhW2MoIlNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lIiwgIlNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lIildLAogIG5hbWVzID0gYygiV2l0aCBTbWFydHBob25lIiwgIldpdGhvdXQgU21hcnRwaG9uZSIpLAogIGNvbCA9IGMoInBpbmsiLCAibGlnaHQgZ3JlZW4iKSwKICBtYWluID0gIkNvbXBhcmlzb24gb2YgU2xlZXAgUXVhbGl0eSIsCiAgeWxhYiA9ICJTbGVlcCBRdWFsaXR5IgopCgpgYGAKCkZyb20gdGhlIGFib3ZlIGJveCBwbG90LCB3ZSBjYW4gdmlzdWFsbHkgY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHNsZWVwIHF1YWxpdHkgc2NvcmVzIHdpdGggYW5kIHdpdGhvdXQgc21hcnRwaG9uZSB1c2FnZS4gKipUaGUgYm94IGZvciB3aXRoIHNtYXJ0cGhvbmUgdXNhZ2UgYXBwZWFycyBsb3dlciBhbmQgc2xpZ2h0bHkgbmFycm93ZXIgdGhhbiB0aGUgYm94IGZvciB3aXRob3V0IHNtYXJ0cGhvbmUgdXNhZ2UqKiwgaW5kaWNhdGluZyBwb3RlbnRpYWxseSBsb3dlciBzbGVlcCBxdWFsaXR5IHNjb3JlcyBhbmQgYSBzbGlnaHRseSBtb3JlIGNvbmNlbnRyYXRlZCBkaXN0cmlidXRpb24uCgojIyBUd28tdGFpbGVkIHQtdGVzdAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KCiMgVHdvLXNpZGVkIHQtdGVzdCBmb3IgdGhlIGNvbXBhcmlzb24gYmV0d2VlbiBTbGVlcCBRdWFsaXR5ICh3aXRoIFNtYXJ0cGhvbmUpIAojIGFuZCBTbGVlcCBRdWFsaXR5ICh3aXRob3V0IFNtYXJ0cGhvbmUpCnRfdGVzdF9yZXN1bHQgPC0gdC50ZXN0KAogIHNhbXBsZV9kYXRhJFNsZWVwX1F1YWxpdHlfd2l0aF9TbWFydHBob25lLAogIHNhbXBsZV9kYXRhJFNsZWVwX1F1YWxpdHlfd2l0aG91dF9TbWFydHBob25lLAogIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIgICMgUGVyZm9ybSBhIHR3by1zaWRlZCB0ZXN0CikKIyBQcmludCB0aGUgdC10ZXN0IHJlc3VsdAp0X3Rlc3RfcmVzdWx0CmBgYAoKIyBSZXN1bHQgRGlzY3Vzc2lvbgoKVGhlICoqdHdvLXRhaWxlZCB0LXRlc3QqKiBpcyBhIHN0YXRpc3RpY2FsIHRlc3QgdXNlZCB0byBkZXRlcm1pbmUgaWYgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW5zIG9mIHR3byBpbmRlcGVuZGVudCBncm91cHMuIEluIHRoaXMgcmVzZWFyY2gsIGl0J3MgdXNlZCB0byBjb21wYXJlIHRoZSBzbGVlcCBxdWFsaXR5IG9mIGluZGl2aWR1YWxzIHdpdGggc21hcnRwaG9uZSB1c2FnZSBiZWZvcmUgYmVkdGltZSBhbmQgdGhvc2Ugd2l0aG91dC4KCkluIHRoZSByZXN1bHQsICoqdC12YWx1ZSBpcyAtNS43NDk0KiosIGl0J3MgbmVnYXRpdmUsIGluZGljYXRpbmcgdGhhdCB0aGUgbWVhbiBzbGVlcCBxdWFsaXR5IHdpdGhvdXQgYSBzbWFydHBob25lIGlzIHNpZ25pZmljYW50bHkgaGlnaGVyIHRoYW4gdGhlIG1lYW4gc2xlZXAgcXVhbGl0eSB3aXRoIGEgc21hcnRwaG9uZS4gVGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBpcyBhcHByb3hpbWF0ZWx5IDI3Ljg5My4gVGhpcyB2YWx1ZSBpcyBpbXBvcnRhbnQgZm9yIGRldGVybWluaW5nIHRoZSBjcml0aWNhbCB0LXZhbHVlIGFuZCBjYWxjdWxhdGluZyB0aGUgcC12YWx1ZS4gVGhlICoqcC12YWx1ZSBpcyAzLjY0OWUtMDYqKiwgd2hpY2ggaXMgYSB0b28gc21hbGwgY2xvc2UgdG8gemVyby4gVGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBzdWdnZXN0cyBzdHJvbmcgZXZpZGVuY2UgYWdhaW5zdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGUgYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyBzdGF0ZXMgdGhhdCB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIG5vdCBlcXVhbCB0byAwLiBJbiBvdGhlciB3b3JkcywgaXQgc3VnZ2VzdHMgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgc2xlZXAgcXVhbGl0eSBvZiB0aGVzZSB0d28gZ3JvdXBzLiA5NSBwZXJjZW50IGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgWy0yLjM5NTQzNSwgLTEuMTM2NzYxXSwgdGhpcyBpbnRlcnZhbCBwcm92aWRlcyBhIHJhbmdlIG9mIHZhbHVlcyB3aXRoaW4gd2hpY2ggd2UgY2FuIGJlIDk1IHBlcmNlbnQgY29uZmlkZW50IHRoYXQgdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBtZWFucyBsaWVzLiBJbiB0aGlzIGNhc2UsIGl0IGRvZXNuJ3QgaW5jbHVkZSAwLCB3aGljaCBzdXBwb3J0aW5nIHRoZSAqKipyZWplY3Rpb24gb2YgdGhlIG51bGwgaHlwb3RoZXNpcyoqKi4gVGhlIHNhbXBsZSBtZWFuIG9mIHNsZWVwIHF1YWxpdHkgd2l0aCBhIHNtYXJ0cGhvbmUgaXMgYXBwcm94aW1hdGVseSA2LjI5NTI5MCwgd2hpbGUgdGhlIHNhbXBsZSBtZWFuIHdpdGhvdXQgYSBzbWFydHBob25lIGlzIGFwcHJveGltYXRlbHkgOC4wNjEzODcuIFRoZXJlZm9yZSwgb24gYXZlcmFnZSBzbGVlcCBxdWFsaXR5IHdpdGhvdXQgYSBzbWFydHBob25lIGlzIGhpZ2hlciB0aGFuIHNsZWVwIHF1YWxpdHkgd2l0aCBhIHNtYXJ0cGhvbmUuCgojIENvbW1lbnRzCgpUaGUgcmVzdWx0cyBvZiBvdXIgdC10ZXN0IHByb3ZpZGUgc3Ryb25nIHN0YXRpc3RpY2FsIGV2aWRlbmNlIHRoYXQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHNsZWVwIHF1YWxpdHkgYmV0d2VlbiBpbmRpdmlkdWFscyB3aG8gdXNlIHNtYXJ0cGhvbmVzIGJlZm9yZSBiZWR0aW1lIGFuZCB0aG9zZSB3aG8gZG8gbm90LiBUaGUgbmVnYXRpdmUgdC12YWx1ZSBhbmQgdGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBpbmRpY2F0ZSB0aGF0IHNsZWVwIHF1YWxpdHkgaXMgc2lnbmlmaWNhbnRseSBiZXR0ZXIgd2hlbiBzbWFydHBob25lcyBhcmUgbm90IHVzZWQgYmVmb3JlIHNsZWVwLiBBZGRpdGlvbmFsbHksIHRoZSBjb25maWRlbmNlIGludGVydmFsIGRvZXMgbm90IGluY2x1ZGUgMCwgcmVpbmZvcmNpbmcgdGhlIGNvbmNsdXNpb24gdGhhdCB0aGUgdHdvIGdyb3VwcyBoYXZlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHNsZWVwIHF1YWxpdHkuCgojIExpbWl0YXRpb25zCgpPdXIgc3R1ZHkgaGFzIGxpbWl0YXRpb25zLiBTb21lIG9mIHRoZW0gYXJlIHRoZSBzYW1wbGUgc2l6ZSwgbmFycm93IGJhc2Ugb2YgdGhlIHBvcHVsYXRpb24gYW5kIHRoZSBsaW1pdGF0aW9uIG9mIHRpbWUgd2UgaGF2ZSB0byBjb25kdWN0IHRoaXMgc3R1ZHkuIEFub3RoZXIgZmFjdG9yIGlzIHRoZSBzdHVkeSBkZXNpZ24sIHdoaWNoIGlzIGNyb3NzLXNlY3Rpb25hbC4gVGhpcyB3aWxsIG5vdCBzaG93IGEgY2F1c2UtZWZmZWN0IG9mIHNtYXJ0cGhvbmUgdXNhZ2UgYXQgYmVkdGltZSBvbiBzbGVlcCBxdWFsaXR5LCBidXQgbWlnaHQgaGlnaGxpZ2h0IHRoZSBwcm9ibGVtIHRvIHN0aW11bGF0ZSBvdGhlciBpbnZlc3RpZ2F0b3JzIHRvIGRpZyBtb3JlIGludG8gaXQuIE1vcmVvdmVyLCB0aGUgdHlwZSBvZiBxdWVzdGlvbm5haXJlIHdhcyBzZWxmLWFkbWluaXN0ZXJlZCB3aGljaCBtaWdodCBicmluZyB1cCBzb21lIGlzc3VlcyBsaWtlIG1pc3NpbmcgaXRlbXMgcmVzcG9uc2VzIGFuZCByZWNhbGwgYmlhcyBjb21wYXJlZCB0byBhIGZhY2UtdG8tZmFjZSBpbnRlcnZpZXcuCgojIENvbmNsdXNpb25zCgpUaGlzIHJlc2VhcmNoIGluZGljYXRlcyBhIHBvdGVudGlhbCBsaW5rIGJldHdlZW4gaW5jcmVhc2VkIHNtYXJ0cGhvbmUgdXNlIGJlZm9yZSBiZWR0aW1lIGFuZCBhIGhpZ2hlciBsaWtlbGlob29kIG9mIGV4cGVyaWVuY2luZyBwb29yIHNsZWVwIHF1YWxpdHkuIEhvd2V2ZXIsIGl0J3MgY3J1Y2lhbCB0byBub3RlIHRoYXQgdGhpcyBzdHVkeSBpcyBjcm9zcy1zZWN0aW9uYWwgaW4gbmF0dXJlLCB0aGF0IG1lYW5zIGl0IGRvZXNuJ3QgZXN0YWJsaXNoIGEgY2F1c2UtYW5kLWVmZmVjdCByZWxhdGlvbnNoaXAuIFRvIGdldCBhIGJldHRlciB1bmRlcnN0YW5kIHRoaXMgY29ubmVjdGlvbiwgbW9yZSBleHRlbnNpdmUgaW52ZXN0aWdhdGlvbnMgYW5kIGxhcmdlciBhbmQgZGl2ZXJzZSBwYXJ0aWNpcGFudCBncm91cHMgYXJlIHJlcXVpcmVkLCBhcyB3ZWxsIGFzIHJlc2VhcmNoIGRlc2lnbnMgY2FwYWJsZSBvZiB1bmNvdmVyaW5nIGNhdXNhbCByZWxhdGlvbnNoaXBzLgoKXG5ld3BhZ2UKCiMgKipFeHBsb3JpbmcgdGhlIENvcnJlbGF0aW9uIEJldHdlZW4gTGlmZSBFeHBlY3RhbmN5IGFuZCBHRFAgcGVyIENhcGl0YSBUaHJvdWdoIE1hY2hpbmUgTGVhcm5pbmcgTW9kZWxzKioKCiMgSW50cm9kdWN0aW9uCgpJbiB0aGUgcmVhbG0gb2YgZGF0YSBhbmFseXRpY3MsIHVuZGVyc3RhbmRpbmcgdGhlIGludHJpY2F0ZSBkeW5hbWljcyBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR3Jvc3MgRG9tZXN0aWMgUHJvZHVjdCAoR0RQKSBwZXIgY2FwaXRhIHN0YW5kcyBhcyBhIHBpdm90YWwgZW5kZWF2b3IuIExpZmUgZXhwZWN0YW5jeSwgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHllYXJzIGEgcGVyc29uIGlzIGV4cGVjdGVkIHRvIGxpdmUsIHNlcnZlcyBhcyBhIHByb2ZvdW5kIGluZGljYXRvciBvZiBhIG5hdGlvbidzIG92ZXJhbGwgaGVhbHRoIGFuZCBzb2NpZXRhbCB3ZWxsLWJlaW5nLiBPbiB0aGUgb3RoZXIgaGFuZCwgR0RQIHBlciBjYXBpdGEsIHJlcHJlc2VudGluZyB0aGUgZWNvbm9taWMgb3V0cHV0IHBlciBwZXJzb24sIG1pcnJvcnMgdGhlIGZpbmFuY2lhbCBwcm9zcGVyaXR5IG9mIGEgbmF0aW9uJ3MgY2l0aXplbnMuCgpUaGlzIHByb2plY3QgaW52ZXN0aWdhdGVzIGludG8gdGhlIGludHJpY2F0ZSBjb25uZWN0aW9uIGJldHdlZW4gdHdvIHZpdGFsIGFzcGVjdHMgb2YgYSBjb3VudHJ5J3Mgd2VsbC1iZWluZzogbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YS4gSW5zcGlyZWQgYnkgdGhlIGltcGFjdGZ1bCBHYXBtaW5kZXIgcHJvamVjdCwgY28tZm91bmRlZCBieSB0aGUgZXN0ZWVtZWQgSGFucyBSb3NsaW5nLFtsaW5rXShodHRwczovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWhWaW1Wemd0RDZ3KSBhIGxlYWRpbmcgZmlndXJlIGluIHN0YXRpc3RpY3MgYW5kIHB1YmxpYyBoZWFsdGgsIHRoaXMgdmVudHVyZSBsZXZlcmFnZXMgdGhlIGV4dGVuc2l2ZSBhbmQgZ2xvYmFsbHkgZGl2ZXJzZSBHYXBtaW5kZXIgZGF0YXNldC4gVGhyb3VnaCBSb3NsaW5nJ3MgY29tcGVsbGluZyBwcmVzZW50YXRpb25zLCB0aGlzIGRhdGFzZXQgaGFzIGJlY29tZSBpbnN0cnVtZW50YWwgaW4gcG9wdWxhcml6aW5nIG5hcnJhdGl2ZXMgZ3JvdW5kZWQgaW4gZGF0YSwgZXNwZWNpYWxseSBjb25jZXJuaW5nIGdsb2JhbCBkZXZlbG9wbWVudC4KClRoZSBHYXBtaW5kZXIgZGF0YXNldCwgYSBjb21wcmVoZW5zaXZlIHJlcG9zaXRvcnkgb2YgaW5mb3JtYXRpb24gY29sbGVjdGVkIGZyb20gZGl2ZXJzZSBjb3VudHJpZXMgb3ZlciB0aGUgeWVhcnMsIHNlcnZlcyBhcyBhbiBpZGVhbCByZXNvdXJjZSBmb3IgZXhwbG9yaW5nIHNvY2lvLWVjb25vbWljIGluZGljYXRvcnMuIFdoaWxlIEdhcG1pbmRlciBpcyByZW5vd25lZCBmb3IgaXRzIGJyb2FkIHNjb3BlLCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgZm9yIHRoaXMgcHJvamVjdCwgSSdtIHV0aWxpemluZyBhIGRhdGFzZXQgc291cmNlZCBmcm9tIHRoZSBXb3JsZCBCYW5rLiBUaGlzIGRhdGFzZXQgZW5jYXBzdWxhdGVzIGRhdGEgZnJvbSB2YXJpb3VzIGNvdW50cmllcywgb2ZmZXJpbmcgYSBsb25naXR1ZGluYWwgcGVyc3BlY3RpdmUgc3Bhbm5pbmcgbXVsdGlwbGUgeWVhcnMsIGN1bG1pbmF0aW5nIGluIDIwMTguW0dhcG1pbmRlciBXZWJzaXRlXShodHRwczovL3d3dy5nYXBtaW5kZXIub3JnLykKCgpJbiBkZWx2aW5nIGludG8gdGhlIGludHJpY2F0ZSBmYWN0b3JzIGluZmx1ZW5jaW5nIGxpZmUgZXhwZWN0YW5jeSwgc3VjaCBhcyBoYXBwaW5lc3MsIHBvbGx1dGlvbiwgdGVycm9yaXNtLCBhbmQgZGlzZWFzZXMsIG15IHByaW1hcnkgZm9jdXMgaGFzIGJlZW4gb24gYSBzcGVjaWZpYyBhc3BlY3QsIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgdGhlIEdEUCBwZXIgY2FwaXRhIG9mIGVhY2ggY291bnRyeS4gVGhlIHJlc3VsdHMgdW5kZXJzY29yZSBhIG5vdGFibGUgdHJlbmQg4oCTIGNvdW50cmllcyB3aXRoIGEgaGlnaGVyIEdEUCBwZXIgY2FwaXRhIGdlbmVyYWxseSBleGhpYml0IGEgc3VwZXJpb3IgbGlmZSBleHBlY3RhbmN5IGZvciB0aGVpciBjaXRpemVucywgc3VycGFzc2luZyBvdXRjb21lcyBvYnNlcnZlZCBpbiBjb3VudHJpZXMgd2l0aCBhIGxvd2VyIEdEUCBwZXIgY2FwaXRhIFtAOTU3OTU5NF0uCgpUaGUgb3V0Y29tZXMgYW5kIGluc2lnaHRzIGRlcml2ZWQgZnJvbSB0aGlzIHByb2plY3QgYXJlIGludGVuZGVkIHRvIHNoaW5lIGEgbGlnaHQgb24gdGhlIGZhY3RvcnMgaW1wYWN0aW5nIGxpZmUgZXhwZWN0YW5jeSB3b3JsZHdpZGUuIFRoZXNlIGZpbmRpbmdzIGFpbSB0byBwcm92aWRlIGd1aWRhbmNlIGZvciBwb2xpY3kgZGVjaXNpb25zLCBpbmZvcm0gc29jaW8tZWNvbm9taWMgc3RyYXRlZ2llcywgYW5kIHNoYXBlIHB1YmxpYyBoZWFsdGggaW5pdGlhdGl2ZXMuIEVtcGxveWluZyBhIGNvbXByZWhlbnNpdmUgYXBwcm9hY2gsIHRoaXMgcHJvamVjdCBzZWVrcyB0byBjb250cmlidXRlIHZhbHVhYmxlIHBlcnNwZWN0aXZlcyB0byB0aGUgb25nb2luZyBkaXNjdXNzaW9ucyByZWdhcmRpbmcgdGhlIGNvbXBsZXggcmVsYXRpb25zaGlwIGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5IGluIGRpdmVyc2UgZ2xvYmFsIHNldHRpbmdzLgoKIyBQcm9ibGVtIFN0YXRlbWVudAoKVGhlIHByaW1hcnkgZ29hbCBvZiB0aGlzIHByb2plY3QgaXMgdG8gdW5yYXZlbCBob3cgbGlmZSBleHBlY3RhbmN5IGNvcnJlbGF0ZXMgd2l0aCB0aGUgZWNvbm9taWMgcHJvc3Blcml0eSBvZiBuYXRpb25zLiBCeSBleGFtaW5pbmcgdGhpcyByZWxhdGlvbnNoaXAsIEkgYWltIHRvIGdhaW4gaW5zaWdodHMgaW50byB0aGUgZHluYW1pY3MgdGhhdCBzaGFwZSB0aGUgd2VsbC1iZWluZyBvZiBwb3B1bGF0aW9ucyBhY3Jvc3MgZGlmZmVyZW50IGNvdW50cmllcy4gVGhyb3VnaCBkYXRhLWRyaXZlbiBtZXRob2RvbG9naWVzIGFuZCBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscywgdGhpcyBwcm9qZWN0IGVuZGVhdm9ycyB0byBjb250cmlidXRlIG1lYW5pbmdmdWwgcGVyc3BlY3RpdmVzIHRvIHRoZSBvbmdvaW5nIGRpc2NvdXJzZSBvbiBnbG9iYWwgZGV2ZWxvcG1lbnQuCgoKIyBEYXRhIENvbGxlY3Rpb24gYW5kIFByZS1wcm9jZXNzaW5nCgpJbiB0aGlzIHByb2plY3QgZGF0YXNldHMgc291cmNlZCBmcm9tIHRoZSBXb3JsZCBCYW5rIGZvciB0aGUgYW5hbHlzaXMuIFRvIGRldGVybWluZSBhIHN1aXRhYmxlIHNhbXBsZSBwZXJpb2QsIEkgc2NydXRpbml6ZWQgdGhlIGRhdGEgdG8gaWRlbnRpZnkgcGVyaW9kcyB3aXRoIG1pbmltYWwgbWlzc2luZyB2YWx1ZXMuIENvbnNlcXVlbnRseSwgSSBjaG9zZSB0aGUgZXhwYW5zaXZlIHRpbWVmcmFtZSBzcGFubmluZyBmcm9tIDE5NjAgdG8gMjAxOCBhY3Jvc3MgMTkzIGNvdW50cmllcy4gRHVyaW5nIGRhdGEgcHJlcHJvY2Vzc2luZywgSSByZW1vdmVkIG9ic2VydmF0aW9ucyB0aGF0IGRpZCBub3QgcGVydGFpbiB0byBpbmRpdmlkdWFsIGNvdW50cmllcywgcHJpbWFyaWx5IGZvY3VzaW5nIG9uIGVsaW1pbmF0aW5nIHJlZ2lvbmFsIGFuZCBnbG9iYWwgYXZlcmFnZXMgdG8gbWFpbnRhaW4gZGF0YSBpbnRlZ3JpdHkgYW5kIGFjY3VyYWN5LiBbV29ybGQgQmFua2QgRGF0YV0oaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcpCgpUaGUgaW5pdGlhbCBzdGVwIGluIGFuYWx5emluZyB0aGUgY29sbGVjdGVkIGRhdGFzZXQgaW52b2x2ZWQgbWV0aWN1bG91cyBwcmUtcHJvY2Vzc2luZy4gRGF0YSBwcmUtcHJvY2Vzc2luZyBpcyBlc3NlbnRpYWwgYXMgaXQgcmVhZGllcyB0aGUgZGF0YXNldCBmb3IgYW5hbHlzaXMgb3IgbW9kZWwgZGV2ZWxvcG1lbnQuIFRoaXMgcHJvY2VzcyBpbmNsdWRlcyB0cmFuc2Zvcm1pbmcgdGhlIGRhdGEgaW50byB1c2FibGUgZm9ybWF0cyBhbmQgcmVjdGlmeWluZyBpcnJlZ3VsYXJpdGllcywgc3VjaCBhcyBOYU4gdmFsdWVzLCB3aGljaCBjYW4gc2lnbmlmaWNhbnRseSBpbXBhY3QgcmVzdWx0IGFjY3VyYWN5LgoKVGhlIGRhdGFzZXQgZXh0cmFjdGVkIGZvciB0aGlzIHN0dWR5IHdhcyBpbiB0aGUgZGVzaXJlZCBDU1YgZm9ybWF0LiBIb3dldmVyLCBpdCBkaWQgY29udGFpbiBtaXNzaW5nIG9yIHVuaWRlbnRpZmllZCB2YWx1ZXMuIERhdGFzZXRzIHdpdGggdGhlc2UgZ2FwcyBjYW4gY29tcHJvbWlzZSB0aGUgcHJlY2lzaW9uIG9mIGRhdGEgYW5hbHlzaXMgYW5kIG1vZGVsIHByZWRpY3Rpb25zLiBDb25zZXF1ZW50bHksIHRoaXMgcmVzZWFyY2ggdG9vayB0aGUgYXBwcm9hY2ggb2YgcmVtb3ZpbmcgYWxsIGluc3RhbmNlcyB3aXRoIG1pc3NpbmcgdmFsdWVzLCBsZWFkaW5nIHRvIHRoZSBlbGltaW5hdGlvbiBvZiBhcHByb3hpbWF0ZWx5IDQ0JSBvZiB0aGUgZGF0YXNldC4gQWRkaXRpb25hbGx5LCBpcnJlbGV2YW50IGFuZCByZWR1bmRhbnQgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQgZHVyaW5nIHRoZSBhbmFseXNpcy4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KCmRhdGEgPC0gcmVhZC5jc3YoIkxpZmUgRXhwZWN0YW5jeSB2cyBHRFAuY3N2IiwgaGVhZGVyID0gVFJVRSkKCiNoZWFkKGRhdGEpICAjIFRvIHNlZSB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgdGhlIGRhdGFzZXQKI3RhaWwoZGF0YSkKI3N1bW1hcnkoZGF0YSkKCmBgYAoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgQ2hlY2sgdGhlIGN1cnJlbnQgY29sdW1uIG5hbWVzCiNwcmludChjb2xuYW1lcyhkYXRhKSkKCgojIENoYW5nZSB0aGUgY29sdW1uIG5hbWUgZnJvbSAnR0RQLnBhciBDYXAnIHRvICdHRFAnCmNvbG5hbWVzKGRhdGEpW2NvbG5hbWVzKGRhdGEpID09ICJHRFAucGVyLmNhcGl0YSJdIDwtICJnZHBfcGVyX2NhcGl0YSIKCiMgQ2hhbmdlIHRoZSBjb2x1bW4gbmFtZSBmcm9tICdHRFAucGFyIENhcCcgdG8gJ0dEUCcKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIkxpZmUuZXhwZWN0YW5jeSJdIDwtICJMaWZlRXhwIgoKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIlBvcHVsYXRpb24uLmhpc3RvcmljYWwuZXN0aW1hdGVzLiJdIDwtICJwb3AiCgoKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIkVudGl0eSJdIDwtICJjb3VudHJ5Igpjb2xuYW1lcyhkYXRhKVtjb2xuYW1lcyhkYXRhKSA9PSAiQ29udGluZW50Il0gPC0gImNvbnRpbmVudCIKY29sbmFtZXMoZGF0YSlbY29sbmFtZXMoZGF0YSkgPT0gIlllYXIiXSA8LSAieWVhciIKCiMgVmVyaWZ5IHRoZSBjaGFuZ2VzCiNwcmludChjb2xuYW1lcyhkYXRhKSkKCiMgUmVtb3ZlIG1pc3NpbmcgdmFsdWVzIChpZiBhbnkpCiNkYXRhIDwtIG5hLm9taXQoZGF0YSkKCgpgYGAKCiMjIERhdGEgU3BsaXR0aW5nCgpCZWZvcmUgYnVpbGRpbmcgYW55IG1vZGVsIGl0J3MgZXNzZW50aWFsIHRvIHByZXByb2Nlc3MgdGhlIGRhdGEuIEluIHRoaXMgY2FzZSwgd2Ugd2lsbCBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMsIDcwJSBmb3IgdHJhaW5pbmcgYW5kIDMwJSBmb3IgdGVzdGluZy4KYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgNzAlIGZvciB0cmFpbmluZywgMzAlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjcgKiBucm93KGRhdGEpKQoKIyBTcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMKdHJhaW5fZGF0YSA8LSBkYXRhWzE6c3BsaXRfcG9pbnQsIF0KdGVzdF9kYXRhIDwtIGRhdGFbKHNwbGl0X3BvaW50ICsgMSk6bnJvdyhkYXRhKSwgXQpgYGAKCiMgTWV0aG9kcwoKVmlzdWFsaXphdGlvbiBwbGF5cyBhIGNydWNpYWwgcm9sZSBpbiB0aGlzIGV4cGxvcmF0aW9uLCBpbGx1c3RyYXRpbmcgdGhlIHRlbXBvcmFsIGV2b2x1dGlvbiBvZiBsaWZlIGV4cGVjdGFuY3kgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMgdGhyb3VnaG91dCB0aGUgeWVhcnMuIFRocm91Z2ggZHluYW1pYyB2aXN1YWxpemF0aW9ucywgdGhpcyBwcm9qZWN0IHdpbGwgaGlnaGxpZ2h0IGdsb2JhbCB0cmVuZHMgaW4gbGlmZSBleHBlY3RhbmN5LCBpZGVudGlmeWluZyBwYXR0ZXJucyBhbmQgdmFyaWF0aW9ucyBhY3Jvc3MgY29udGluZW50cyBhbmQgcmVnaW9ucy4gSSdsbCBhbHNvIGxvb2sgYXQgdGhlIG51bWJlcnMgdG8gc2VlIGlmIHRoZXJlJ3MgYSBzdHJvbmcgY29ubmVjdGlvbiBiZXR3ZWVuIGhvdyBtdWNoIG1vbmV5IGEgY291bnRyeSBtYWtlcyBhbmQgaG93IGxvbmcgcGVvcGxlIGxpdmUuIFRoZSBpbnZlc3RpZ2F0aW9uIGV4cGFuZHMgZnVydGhlciB3aXRoIHRoZSB1c2Ugb2YgYm94IHBsb3RzLCBwcm92aWRpbmcgaW5zaWdodHMgaW50byBob3cgbGlmZSBleHBlY3RhbmN5IHZhcmllcyBjb250aW5lbnQtd2lzZSwgYWRkaW5nIGEgbGF5ZXIgb2YgZGV0YWlsIHRvIHRoZSBhbmFseXNpcy4KCgpJbiBvcmRlciB0byBnYXVnZSB0aGUgaW50cmljYXRlIGNvbm5lY3Rpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhLCAKVG8gbWVhc3VyZSB0aGUgY29ubmVjdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEsIEkgd2lsbCBjb25kdWN0IGEgbXVsdGlmYWNldGVkIHN0YXRpc3RpY2FsIGFuYWx5c2lzLiBUaGUgbWV0aG9kb2xvZ3kgaW5jbHVkZXMgaHlwb3RoZXNpcyB0ZXN0aW5nLCBMaW5lYXIgUmVncmVzc2lvbiBBbmFseXNpcywgYW5kIFJhbmRvbSBGb3Jlc3QgbW9kZWxpbmcuIFRoZSByZXN1bHRzIGRlcml2ZWQgZnJvbSB0aGVzZSB0d28gbWV0aG9kcyB3aWxsIGJlIHJpZ29yb3VzbHkgY29tcGFyZWQgd2l0aCB0aG9zZSBvYnRhaW5lZCB0aHJvdWdoIHRoZSB1dGlsaXphdGlvbiBvZiBTdXBwb3J0IFZlY3RvciBNYWNoaW5lIGFuZCBHcmFkaWVudCBCb29zdGluZyB0ZWNobmlxdWVzLiBBZGRpdGlvbmFsbHksIEkgd2lsbCB1c2UgY29ycmVsYXRpb24gYW5hbHlzaXMgdG8gcmV2ZWFsIHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhLiBUaGlzIGNvbXByZWhlbnNpdmUgYXBwcm9hY2ggYWltcyB0byBwcm92aWRlIGEgdGhvcm91Z2ggdW5kZXJzdGFuZGluZyBvZiBob3cgdGhlc2UgdHdvIGZhY3RvcnMgYXJlIGxpbmtlZC4gRXZhbHVhdGlvbiBtZXRyaWNzIGxpa2UgUi1zcXVhcmVkIGFuZCBSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSkgd2lsbCBiZSB1dGlsaXplZCB0byBjb21wYXJlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGVzZSBtb2RlbHMsIHByb3ZpZGluZyBhIGNvbXByZWhlbnNpdmUgdW5kZXJzdGFuZGluZyBvZiB0aGVpciBwcmVkaWN0aXZlIGNhcGFiaWxpdGllcy4KClRoZSByZXN1bHRzIGFuZCBjb25jbHVzaW9ucyBkcmF3biBmcm9tIHRoaXMgcHJvamVjdCBhaW0gdG8gaWxsdW1pbmF0ZSB0aGUgZmFjdG9ycyBpbmZsdWVuY2luZyBnbG9iYWwgbGlmZSBleHBlY3RhbmN5LCBvZmZlcmluZyBpbnNpZ2h0cyB0aGF0IGNhbiBndWlkZSBwb2xpY3kgZGVjaXNpb25zLCBpbmZvcm0gc29jaW8tZWNvbm9taWMgc3RyYXRlZ2llcywgYW5kIHNoYXBlIHB1YmxpYyBoZWFsdGggaW5pdGlhdGl2ZXMuIFRocm91Z2ggYSBtdWx0aWZhY2V0ZWQgYXBwcm9hY2gsIHRoaXMgcHJvamVjdCBhc3BpcmVzIHRvIGNvbnRyaWJ1dGUgbWVhbmluZ2Z1bCBwZXJzcGVjdGl2ZXMgdG8gdGhlIG9uZ29pbmcgZGlzY291cnNlIG9uIHRoZSBpbnRyaWNhdGUgaW50ZXJwbGF5IGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5IGFjcm9zcyBkaXZlcnNlIGdsb2JhbCBjb250ZXh0cy4KCiMjIENob3JvcGxldGggTWFwCgpBIGNob3JvcGxldGggbWFwIGlzIGEgdHlwZSBvZiB0aGVtYXRpYyBtYXAgdGhhdCB1c2VzIGNvbG9ycyBvciBzaGFkaW5nIHRvIHJlcHJlc2VudCBzdGF0aXN0aWNhbCBkYXRhIGFjcm9zcyBnZW9ncmFwaGljIHJlZ2lvbnMgb3IgYXJlYXMuIFRoZSBpbnRlbnNpdHkgb2YgY29sb3Igb3Igc2hhZGluZyB2YXJpZXMgYmFzZWQgb24gdGhlIG1hZ25pdHVkZSBvZiB0aGUgZGF0YSBiZWluZyByZXByZXNlbnRlZCwgYWxsb3dpbmcgdmlld2VycyB0byBxdWlja2x5IGdyYXNwIHBhdHRlcm5zIG9yIHZhcmlhdGlvbnMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9uZXdwbG90LnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKClRoZSBhYm92ZSBjaG9yb3BsZXRoIG1hcCBpcyB2aXN1YWxpemluZyAgbGlmZSBleHBlY3RhbmN5IGRhdGEgYWNyb3NzIGRpZmZlcmVudCBjb3VudHJpZXMgb3IgcmVnaW9ucyBpbiB0aGUgeWVhciAyMDE4LiBEYXJrZXIgb3IgbW9yZSBpbnRlbnNlIGNvbG9ycyBtYXkgcmVwcmVzZW50IGhpZ2hlciBsaWZlIGV4cGVjdGFuY3ksIHdoaWxlIGxpZ2h0ZXIgY29sb3JzIGluZGljYXRlIGxvd2VyIGxpZmUgZXhwZWN0YW5jeS4gVGhpcyB0eXBlIG9mIG1hcCBwcm92aWRlcyBhIHZpc3VhbCBzdW1tYXJ5IG9mIHRoZSBkaXN0cmlidXRpb24gb2YgbGlmZSBleHBlY3RhbmN5LCBtYWtpbmcgaXQgZWFzaWVyIHRvIGlkZW50aWZ5IGdsb2JhbCB0cmVuZHMgYW5kIGRpc3Bhcml0aWVzLlRoaXMgbWFwIGlzIGEgcG93ZXJmdWwgdG9vbCBmb3IgdW5kZXJzdGFuZGluZyBob3cgd2VsbC1iZWluZyBpcyBkaXN0cmlidXRlZCBnZW9ncmFwaGljYWxseSwgaGlnaGxpZ2h0aW5nIGNsZWFyIGRpZmZlcmVuY2VzIGJldHdlZW4gY291bnRyaWVzIGFuZCBjb250aW5lbnRzLiAKCgojIyBTY2F0dGVyIFBsb3QgZm9yIExpZmUgRXhwZWN0YW5jeSB2cyBHRFAgcGVyIENhcGl0YQoKQSBzY2F0dGVyIHBsb3QgaXMgdXNlZnVsIGZvciBpZGVudGlmeWluZyB0cmVuZHMsIGNvcnJlbGF0aW9ucywgb3IgcGF0dGVybnMgaW4gdGhlIGRhdGEuIEluIHRoZSBiZWxsb3cgc2NhdHRlciBwbG90IGlzIGEgZ3JhcGhpY2FsIHJlcHJlc2VudGF0aW9uIHRoYXQgZGlzcGxheXMgaW5kaXZpZHVhbCBkYXRhIHBvaW50cyBmb3IgZWFjaCBjb3VudHJ5LgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvU2NhdHRlclBsb3QucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIHNjYXR0ZXIgcGxvdCB2aXN1YWxseSByZXByZXNlbnRpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgaW4geWVhciBvZiAyMDE4LCBvZmZlcmluZyBhIGNvbXBlbGxpbmcgaW5zaWdodCBpbnRvIGhvdyB0aGUgZWNvbm9taWMgcHJvc3Blcml0eSBvZiBhIGNvdW50cnkgY29ycmVsYXRlcyB3aXRoIHRoZSBsaWZlIGV4cGVjdGFuY3kgb2YgaXRzIGNpdGl6ZW5zLiBBcyB3ZSBleGFtaW5lIHRoZSBzY2F0dGVyIHBsb3QsIGEgZGlzY2VybmlibGUgcGF0dGVybiBlbWVyZ2Vz4oCUY291bnRyaWVzIHdpdGggaGlnaGVyIEdEUCBwZXIgY2FwaXRhIHRlbmQgdG8gZXhoaWJpdCBpbmNyZWFzZWQgbGlmZSBleHBlY3RhbmN5LgoKRWFjaCBwb2ludCBvbiB0aGUgcGxvdCBjb3JyZXNwb25kcyB0byBhIHNwZWNpZmljIGNvdW50cnksIHdpdGggdGhlIHgtYXhpcyByZXByZXNlbnRpbmcgdGhlIEdEUCBwZXIgY2FwaXRhIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudGluZyBsaWZlIGV4cGVjdGFuY3kuIFRoZSB1cHdhcmQgdHJlbmQgb2JzZXJ2ZWQgaW4gdGhlIHNjYXR0ZXJwbG90IHN1Z2dlc3RzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGVzZSB0d28gdmFyaWFibGVzLiBJbiBzaW1wbGVyIHRlcm1zLCBhcyBhIGNvdW50cnkncyBHRFAgcGVyIGNhcGl0YSBpbmNyZWFzZXMsIHRoZXJlIGlzIGEgbm90YWJsZSByaXNlIGluIGxpZmUgZXhwZWN0YW5jeS4KClRoaXMgcmVsYXRpb25zaGlwIHVuZGVyc2NvcmVzIHRoZSBwb3RlbnRpYWwgaW1wYWN0IG9mIGVjb25vbWljIHdlbGwtYmVpbmcgb24gdGhlIG92ZXJhbGwgaGVhbHRoIGFuZCBsb25nZXZpdHkgb2YgYSBwb3B1bGF0aW9uLiBUaGUgc2NhdHRlcnBsb3Qgc2VydmVzIGFzIGEgdmlzdWFsIG5hcnJhdGl2ZSwgaGlnaGxpZ2h0aW5nIHRoZSB0cmVuZCBhbmQgcmVpbmZvcmNpbmcgdGhlIG5vdGlvbiB0aGF0IGhpZ2hlciBlY29ub21pYyBwcm9zcGVyaXR5IGNvbnRyaWJ1dGVzIHBvc2l0aXZlbHkgdG8gdGhlIGxpZmUgZXhwZWN0YW5jeSBvZiBhIGNvdW50cnkncyByZXNpZGVudHMuCgojIyBCb3ggUGxvdHMKCkEgYm94IHBsb3QgaXMgYSBncmFwaGljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhIGRhdGFzZXQuIEl0IHByb3ZpZGVzIGEgdmlzdWFsIHN1bW1hcnkgb2Yga2V5IHN0YXRpc3RpY2FsIG1lYXN1cmVzIGFuZCBhbGxvdyB0byB1bmRlcnN0YW5kIHRoZSBjZW50cmFsIHRlbmRlbmN5LCBzcHJlYWQsIGFuZCBpZGVudGlmeSBwb3RlbnRpYWwgb3V0bGllcnMgd2l0aGluIHRoZSBkYXRhLgoKSGVyZSBpbiB0aGlzIHByb2plY3QgdGhlIGJveCBwbG90IHNob3djYXNpbmcgbGlmZSBleHBlY3RhbmN5IGRhdGEgYnkgY29udGluZW50IHByb3ZpZGVzIGEgY29uY2lzZSBhbmQgaW5zaWdodGZ1bCB2aXN1YWxpemF0aW9uIG9mIHRoZSBkaXN0cmlidXRpb24gYW5kIGNlbnRyYWwgdGVuZGVuY2llcyBvZiBsaWZlIGV4cGVjdGFuY3kgYWNyb3NzIGRpZmZlcmVudCByZWdpb25zLiBFYWNoIGJveCByZXByZXNlbnRzIGEgY29udGluZW50LCBkaXNwbGF5aW5nIHRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlICwgbWVkaWFuLCBhbmQgcG90ZW50aWFsIG91dGxpZXJzIEBkZXZvcmUyMDE1cHJvYmFiaWxpdHkuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTAucG5nIiwgZXJyb3IgPSBGQUxTRSkKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTMucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGJveCBwbG90IHZpc3VhbGl6aW5nIEdEUCBwZXIgY2FwaXRhIGJ5IGNvbnRpbmVudCwgYSBjb21wZWxsaW5nIHRyZW5kIGVtZXJnZXMgYXMgaGlnaGVyIEdEUCBsZXZlbHMgYXJlIGFzc29jaWF0ZWQgd2l0aCBpbmNyZWFzZWQgTGlmZSBFeHBlY3RhbmN5LiBUaGUgYm94ZXMgY29uc2lzdGVudGx5IHNoaWZ0IHVwd2FyZHMgYWNyb3NzIGNvbnRpbmVudHMgd2l0aCBoaWdoZXIgR0RQLCBpbmRpY2F0aW5nIGEgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBlY29ub21pYyBwcm9zcGVyaXR5IGFuZCB0aGUgb3ZlcmFsbCB3ZWxsLWJlaW5nIG9mIHBvcHVsYXRpb25zLiBUaGlzIG9ic2VydmF0aW9uIHN1Z2dlc3RzIHRoYXQgY291bnRyaWVzIHdpdGggaGlnaGVyIEdEUCBwZXIgY2FwaXRhIHRlbmQgdG8gZXhoaWJpdCBub3Qgb25seSBzdHJvbmdlciBlY29ub21pYyBwZXJmb3JtYW5jZSBidXQgYWxzbyBlbGV2YXRlZCBsaWZlIGV4cGVjdGFuY2llcywgcHJvdmlkaW5nIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIGludGVyY29ubmVjdGVkIGR5bmFtaWNzIG9mIGVjb25vbWljIGRldmVsb3BtZW50IGFuZCBwdWJsaWMgaGVhbHRoIG9uIGEgZ2xvYmFsIHNjYWxlLgoKIyMgSHlwb3RoZXNpcyBUZXN0CgpIeXBvdGhlc2lzIHRlc3RpbmcgZm9yIGNvcnJlbGF0aW9uIGludm9sdmVzIHRlc3Rpbmcgd2hldGhlciB0aGUgb2JzZXJ2ZWQgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvLkluIHRoZSBjb250ZXh0IG9mIHRoaXMgcHJvamVjdCwgd2hlcmUgSSBhbSBleGFtaW5pbmcgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YSwgSSBhbSBmb2xsb3dpbmcgdGhlIHN0ZXBzIGZvciBoeXBvdGhlc2lzIHRlc3RpbmcuCgokJAp7SHlwb3RoZXNpc1wgVGVzdDp9IFxcClxiZWdpbnthbGlnbip9CiYgSF8wOiBcdGV4dHtUaGVyZSBpcyBubyBzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgKFwoXHJobyA9IDBcKSkufSBcXAomIEhfYTogXHRleHR7VGhlcmUgaXMgYSBzaWduaWZpY2FudCBjb3JyZWxhdGlvbiBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEgKFwoXHJobyBcbmVxIDBcKSkufQpcZW5ke2FsaWduKn0KJCQKCiQkCkludGVycHJldFwgUmVzdWx0czoKXGJlZ2lue2FsaWduKn0KJiBcdGV4dHtJZiBwLXZhbHVlfSA8IFxhbHBoYSwgXHRleHR7cmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMufSBcXAomIFx0ZXh0e0lmIHAtdmFsdWV9IFxnZXEgXGFscGhhLCBcdGV4dHtmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLn0KXGVuZHthbGlnbip9CiQkCgpgYGB7cixlY2hvPUZBTFNFfQoKIyBDYWxjdWxhdGUgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQKY29ycmVsYXRpb25fY29lZmZpY2llbnQgPC0gY29yKGRhdGEkTGlmZUV4cCwgZGF0YSRnZHBfcGVyX2NhcGl0YSkKCiMgQ29uZHVjdCBIeXBvdGhlc2lzIFRlc3QKY29yX3Rlc3RfcmVzdWx0IDwtIGNvci50ZXN0KGRhdGEkTGlmZUV4cCwgZGF0YSRnZHBfcGVyX2NhcGl0YSkKCiMgSW50ZXJwcmV0IFJlc3VsdHMKY2F0KCJPYnNlcnZlZCBDb3JyZWxhdGlvbiBDb2VmZmljaWVudDoiLCBjb3JyZWxhdGlvbl9jb2VmZmljaWVudCwgIlxuIikKY2F0KCJwLXZhbHVlOiIsIGNvcl90ZXN0X3Jlc3VsdCRwLnZhbHVlLCAiXG4iKQoKIyBDaGVjayBpZiB0aGUgcC12YWx1ZSBpcyBsZXNzIHRoYW4gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCAoZS5nLiwgMC4wNSkKaWYgKGNvcl90ZXN0X3Jlc3VsdCRwLnZhbHVlIDwgMC4wNSkgewogIGNhdCgiUmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgY29ycmVsYXRpb24uXG4iKQp9IGVsc2UgewogIGNhdCgiRmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhlcmUgaXMgbm90IGVub3VnaCBldmlkZW5jZSBvZiBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uLlxuIikKfQoKYGBgClRoZSBvYnNlcnZlZCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBvZiAwLjYzNDIwNDQgaW5kaWNhdGVzIGEgbW9kZXJhdGUgdG8gc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YS4gVGhlIGV4dHJlbWVseSBsb3cgcC12YWx1ZSBzdWdnZXN0cyB0aGF0IHRoaXMgY29ycmVsYXRpb24gaXMgaGlnaGx5IHVubGlrZWx5IHRvIGhhdmUgb2NjdXJyZWQgYnkgcmFuZG9tIGNoYW5jZSBhbG9uZS4gVGhlcmVmb3JlLCB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGNvcnJlbGF0aW9uIGJldHdlZW4gbGlmZSBleHBlY3RhbmN5IGFuZCBHRFAgcGVyIGNhcGl0YSBpbiB5b3VyIGRhdGFzZXQuCgoKIyMgQ29ycmVsYXRpb24gTWF0cml4CgpBIGNvcnJlbGF0aW9uIG1hdHJpeCBpcyBhIHN0YXRpc3RpY2FsIHRhYmxlIHRoYXQgZGlzcGxheXMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBiZXR3ZWVuIHNldmVyYWwgdmFyaWFibGVzLiBJdCBpcyBhIHN5bW1ldHJpYyBtYXRyaXggd2hlcmUgZWFjaCBjZWxsIHJlcHJlc2VudHMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGJldHdlZW4gdHdvIHZhcmlhYmxlcy4gQ29ycmVsYXRpb24gY29lZmZpY2llbnRzIHF1YW50aWZ5IHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHR3byB2YXJpYWJsZXMuCgpUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgYSBudW1lcmljYWwgdmFsdWUgcmFuZ2luZyBmcm9tIC0xIHRvIDEuCkNvcnJlbGF0aW9uIG9mIDEgaW5kaWNhdGVzIGEgcGVyZmVjdCBwb3NpdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwIGFuZCBjb3JyZWxhdGlvbiBvZiAtMSBpbmRpY2F0ZXMgYSBwZXJmZWN0IG5lZ2F0aXZlIGxpbmVhciwgY29ycmVsYXRpb24gb2YgMCBpbmRpY2F0ZXMgbm8gbGluZWFyIHJlbGF0aW9ucyBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMuCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy8wMDAwMTIucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGJldHdlZW4gTGlmZSBFeHBlY3RhbmN5IGFuZCBHRFAgcGVyIENhcGl0YSBpcyBhcHByb3hpbWF0ZWx5IDAuNjAuIFRoaXMgcG9zaXRpdmUgdmFsdWUgaW5kaWNhdGVzIGEgbW9kZXJhdGUgcG9zaXRpdmUgY29ycmVsYXRpb24sIHN1Z2dlc3RpbmcgdGhhdCBhcyBMaWZlIEV4cGVjdGFuY3kgdGVuZHMgdG8gaW5jcmVhc2UsIEdEUCBwZXIgQ2FwaXRhIGFsc28gdGVuZHMgdG8gaW5jcmVhc2UuIEluIHNpbXBsZXIgdGVybXMsIHRoZXJlIGlzIGEgdGVuZGVuY3kgZm9yIGNvdW50cmllcyB3aXRoIGhpZ2hlciBsaWZlIGV4cGVjdGFuY2llcyB0byBoYXZlIGhpZ2hlciBHRFAgcGVyIENhcGl0YS4KCiMgTW9kZWwgQnVpbGRpbmcgYW5kIFByZWRpY3Rpb24KCiMjIExpbm5lYXIgUmVncmVzc2lvbiBNb2RlbAoKTGluZWFyIFJlZ3Jlc3Npb24gaXMgYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSB1c2VkIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgb25lIG9yIG1vcmUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBJdCBhc3N1bWVzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMsIGFpbWluZyB0byBmaW5kIHRoZSBiZXN0LWZpdHRpbmcgbGluZSB0aGF0IG1pbmltaXplcyB0aGUgc3VtIG9mIHNxdWFyZWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBvYnNlcnZlZCBhbmQgcHJlZGljdGVkIHZhbHVlcyBAbGFudHoyMDE5bWFjaGluZS4KCiQkCkxpbmVhclwgUmVncmVzc2lvblwgRXF1YXRpb246IFxcCiQkCgokJCAKWSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfMSArIFxiZXRhXzIgWF8yICsgXGxkb3RzICsgXGJldGFfbiBYX24gKyBcdmFyZXBzaWxvbiBcXAokJAoKCiQkCkluXCB0aGlzXCBlcXVhdGlvbjogXFwKJCQKJCQKWTogXHRleHR7RGVwZW5kZW50IHZhcmlhYmxlfVxcJCQKCiQkXGJldGFfMDogXHRleHR7WS1pbnRlcmNlcHQsIHRoZSBjb25zdGFudCB0ZXJtfVxcJCQKCiQkXGJldGFfMSwgXGJldGFfMiwgXGxkb3RzLCBcYmV0YV9uOiBcdGV4dHtDb2VmZmljaWVudHMgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyB9IChYXzEsIFhfMiwgXGxkb3RzLCBYX24pXFwkJAoKJCRYXzEsIFhfMiwgXGxkb3RzLCBYX246IFx0ZXh0e0luZGVwZW5kZW50IHZhcmlhYmxlc31cXCQkCgokJApcdmFyZXBzaWxvbjogXHRleHR7RXJyb3IgdGVybSwgcmVwcmVzZW50aW5nIHVub2JzZXJ2ZWQgZmFjdG9ycyBhZmZlY3RpbmcgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS59CiQkCgpMaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IGxpZmUgZXhwZWN0YW5jeToKYGBge3IsZWNobz1GQUxTRX0KCiMgQnVpbGQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbApsbV9tb2RlbCA8LSBsbShMaWZlRXhwIH4gZ2RwX3Blcl9jYXBpdGEsIGRhdGEgPSB0cmFpbl9kYXRhKQoKc3VtbWFyeShsbV9tb2RlbCkKCmBgYAoKSW4gdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHN1Z2dlc3RzIGEgc2lnbmlmaWNhbnQgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gR0RQIHBlciBjYXBpdGEgYW5kIGxpZmUgZXhwZWN0YW5jeS4gQWJvdXQgMzUlIG9mIHRoZSB2YXJpYW5jZSBpbiBsaWZlIGV4cGVjdGFuY3kgY2FuIGJlIGV4cGxhaW5lZCBieSBHRFAgcGVyIGNhcGl0YS4gVGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYW5kIHByb3ZpZGUgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZWNvbm9taWMgcHJvc3Blcml0eSBhbmQgbGlmZSBleHBlY3RhbmN5LgoKCgojIyMgTGluZWFyIFJlZ3Jlc3Npb24gU2NhdHRlciBQbG90IAoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvU2NhdHRlclBsb3RMLnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKClRoZSAgc2NhdHRlcnBsb3QgZm9yIExpbmVhciBSZWdyZXNzaW9uIHNob3dpbmcgdGhlIGNvbm5lY3Rpb24gYmV0d2VlbiBsaWZlIGV4cGVjdGFuY3kgYW5kIEdEUCBwZXIgY2FwaXRhIGFuIGludGVyZXN0aW5nIHBhdHRlcm4uIEluc3RlYWQgb2YgYSBzaW1wbGUgbGluZWFyIHRyZW5kLCB0aGUgcmVsYXRpb25zaGlwIHNlZW1zIHRvIGV4aGliaXQgYSBsb2dhcml0aG1pYyB0cmFqZWN0b3J5LiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBpbmZsdWVuY2Ugb2YgYW4gaW5jcmVhc2UgaW4gR0RQIHBlciBjYXBpdGEgb24gbGlmZSBleHBlY3RhbmN5IHZhcmllcyBhY3Jvc3MgZGlmZmVyZW50IGVjb25vbWljIHNjZW5hcmlvcy4KCkluIHBvb3JlciBjb3VudHJpZXMgYW4gZWxldmF0aW9uIGluIEdEUCBwZXIgY2FwaXRhIHNlZW1zIHRvIHlpZWxkIGEgbW9yZSBzdWJzdGFudGlhbCBwb3NpdGl2ZSBlZmZlY3Qgb24gbGlmZSBleHBlY3RhbmN5IGNvbXBhcmVkIHRvIHdlYWx0aGllciBuYXRpb25zLiBUaGlzIHBoZW5vbWVub24gY2FuIGJlIHJhdGlvbmFsaXplZCBieSBjb25zaWRlcmluZyB0aGF0IGVjb25vbWljYWxseSBkaXNhZHZhbnRhZ2VkIGNvdW50cmllcyBtYXkgZXhwZXJpZW5jZSBzaWduaWZpY2FudCBpbXByb3ZlbWVudHMgaW4gbGlmZSBleHBlY3RhbmN5IHdoZW4gZmluYW5jaWFsIHJlc291cmNlcyBhcmUgZGlyZWN0ZWQgdG93YXJkcyBlbmhhbmNpbmcgaGVhbHRoY2FyZSBpbmZyYXN0cnVjdHVyZSBhbmQgbWVkaWNhbCB0cmVhdG1lbnRzLgoKIyMgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IgTW9kZWwKCkluIG9yZGVyIHRvIGV4cGxvcmUgYSBtb3JlIGFkdmFuY2VkIGFwcHJvYWNoIHRvIHByZWRpY3QgbGlmZSBleHBlY3RhbmN5IGJhc2VkIG9uIEdEUCBwZXIgY2FwaXRhLiBJJ20gdXNpbmcgYSBSYW5kb20gRm9yZXN0IHJlZ3Jlc3Nvci4KClJhbmRvbSBGb3Jlc3QgaXMgYSBwb3dlcmZ1bCBlbnNlbWJsZSBsZWFybmluZyBhbGdvcml0aG0gdXNlZCBmb3IgYm90aCBjbGFzc2lmaWNhdGlvbiBhbmQgcmVncmVzc2lvbiB0YXNrcy4gSXQgd2FzIGludHJvZHVjZWQgYnkgTGVvIEJyZWltYW4gaW4gMjAwMS4gVGhlICJmb3Jlc3QiIGluIFJhbmRvbSBGb3Jlc3QgaXMgYSBjb2xsZWN0aW9uIG9mIGRlY2lzaW9uIHRyZWVzLCBhbmQgdGhlICJyYW5kb20iIHBhcnQgY29tZXMgZnJvbSB0aGUgZmFjdCB0aGF0IGVhY2ggdHJlZSBpcyB0cmFpbmVkIG9uIGEgcmFuZG9tIHN1YnNldCBvZiB0aGUgZGF0YSBhbmQgZmVhdHVyZXMuCgokJApcdGV4dHtSZWdyZXNzaW9uOn1cXCBcaGF0e3l9X3tcdGV4dHtSRn19ID0gXGZyYWN7MX17bn0gXHN1bV97aT0xfV57bn0gXGhhdHt5fV9pIAokJAoKJCQgClx0ZXh0e0NsYXNzaWZpY2F0aW9ufTogXFwKXGhhdHt5fV97XHRleHR7UkZ9fSA9IFx0ZXh0e21vZGV9KFxoYXR7eX1fMSwgXGhhdHt5fV8yLCBcbGRvdHMsIFxoYXR7eX1fbikKJCQKClJhbmRvbSBGb3Jlc3QgaXMgd2lkZWx5IHVzZWQgaW4gdmFyaW91cyBmaWVsZHMgZHVlIHRvIGl0cyB2ZXJzYXRpbGl0eSBhbmQgZWZmZWN0aXZlbmVzcyBpbiBwcm9kdWNpbmcgaGlnaC1xdWFsaXR5IHByZWRpY3Rpb25zLgoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCiMgTG9hZCBsaWJyYXJpZXMKbGlicmFyeShjYXJldCkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCgojIEJ1aWxkIGEgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IgbW9kZWwKcmZfbW9kZWwgPC0gcmFuZG9tRm9yZXN0KExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEsIG50cmVlID0gMTAwKQoKIyBNYWtlIHByZWRpY3Rpb25zIG9uIHRoZSB0ZXN0IHNldAp0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYgPC0gcHJlZGljdChyZl9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkKCiMgQ2FsY3VsYXRlIFItc3F1YXJlZCBzY29yZSBmb3IgUmFuZG9tIEZvcmVzdApyZl9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpIC8gc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIG1lYW4odGVzdF9kYXRhJExpZmVFeHApKV4yKQpwcmludChwYXN0ZSgiUmFuZG9tIEZvcmVzdCBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKHJmX3Jfc3F1YXJlZCwgMikpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgUmFuZG9tIEZvcmVzdCBSZWdyZXNzb3IKcm1zZV9yZiA8LSBzcXJ0KG1lYW4oKHRlc3RfZGF0YSRwcmVkaWN0aW9uc19yZiAtIHRlc3RfZGF0YSRMaWZlRXhwKV4yKSkKcm1zZV9yZgoKIyBEaXNwbGF5IHRoZSBSYW5kb20gRm9yZXN0IG1vZGVsIGRldGFpbHMKcmZfbW9kZWwKYGBgClRoaXMgUmFuZG9tIEZvcmVzdCBtb2RlbCBpcyBzcGVjaWZpZWQgZm9yIHJlZ3Jlc3Npb24sIGluZGljYXRpbmcgdGhhdCBpdCBpcyBkZXNpZ25lZCB0byBwcmVkaWN0IGEgY29udGludW91cyBvdXRjb21lLCB3aGljaCBhbGlnbnMgd2l0aCB0aGUgbmF0dXJlIG9mIHRoZSBsaWZlIGV4cGVjdGFuY3kgdmFyaWFibGUuCgpUaGUgUmFuZG9tIEZvcmVzdCBjb25zaXN0cyBvZiBhbiBlbnNlbWJsZSBvZiBkZWNpc2lvbiB0cmVlcy4gSW4gdGhpcyBjYXNlLCB0aGVyZSBhcmUgMTAwIHRyZWVzIGluIHRoZSBmb3Jlc3QuIEF0IGVhY2ggbm9kZSBvZiBhIGRlY2lzaW9uIHRyZWUsIHRoZSBhbGdvcml0aG0gY29uc2lkZXJzIGEgc3Vic2V0IG9mIHByZWRpY3RvciB2YXJpYWJsZXMgZm9yIHNwbGl0dGluZy4gSGVyZSBvbmx5IDEgdmFyaWFibGUgaXMgdHJpZWQgYXQgZWFjaCBzcGxpdC4gVGhpcyBjYW4gY29udHJpYnV0ZSB0byB0aGUgZGl2ZXJzaXR5IG9mIHRoZSB0cmVlcyBpbiB0aGUgZW5zZW1ibGUuClRoZSBtZWFuIG9mIHNxdWFyZWQgcmVzaWR1YWxzIGlzIGEgbWVhc3VyZSBvZiB0aGUgYXZlcmFnZSBzcXVhcmVkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJlZGljdGVkIGFuZCBhY3R1YWwgdmFsdWVzLiBJbiB0aGlzIGNvbnRleHQsIGl0IGlzIDcwLjE4NDMyLiBBIGxvd2VyIHZhbHVlIGluZGljYXRlcyBiZXR0ZXIgbW9kZWwgZml0LCBzdWdnZXN0aW5nIHRoYXQsIG9uIGF2ZXJhZ2UsIHRoZSBwcmVkaWN0aW9ucyBhcmUgY2xvc2UgdG8gdGhlIGFjdHVhbCBsaWZlIGV4cGVjdGFuY3kgdmFsdWVzLgoKVGhlIHBlcmNlbnRhZ2Ugb2YgdmFyaWFuY2UgZXhwbGFpbmVkIGlzIGEgbWVhc3VyZSBvZiBob3cgbXVjaCB2YXJpYWJpbGl0eSBpbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgaXMgYWNjb3VudGVkIGZvciBieSB0aGUgbW9kZWwuIEluIHRoaXMgY2FzZSwgdGhlIG1vZGVsIGV4cGxhaW5zIDU2LjY4JSBvZiB0aGUgdmFyaWFuY2UgaW4gbGlmZSBleHBlY3RhbmN5LCBpbmRpY2F0aW5nIGEgbW9kZXJhdGUgbGV2ZWwgb2YgZXhwbGFuYXRvcnkgcG93ZXIuCgpPdmVyYWxsLCB0aGVzZSBtZXRyaWNzIHByb3ZpZGUgYW4gb3ZlcnZpZXcgb2YgdGhlIFJhbmRvbSBGb3Jlc3QgbW9kZWwncyBjaGFyYWN0ZXJpc3RpY3MgYW5kIHBlcmZvcm1hbmNlIG9uIHRoZSB0cmFpbmluZyBkYXRhLiBJdCBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBpcyBjYXB0dXJpbmcgYSBzdWJzdGFudGlhbCBwb3J0aW9uIG9mIHRoZSB2YXJpYWJpbGl0eSBpbiBsaWZlIGV4cGVjdGFuY3kgYW5kIGhhcyB0aGUgcG90ZW50aWFsIGZvciBtYWtpbmcgYWNjdXJhdGUgcHJlZGljdGlvbnMuIEhvd2V2ZXIsIHRvIGZ1bGx5IGFzc2VzcyBpdHMgcGVyZm9ybWFuY2UsIGl0J3MgZXNzZW50aWFsIHRvIGV2YWx1YXRlIHRoZSBtb2RlbCBvbiBhIHNlcGFyYXRlIHRlc3QgZGF0YXNldCB0byBlbnN1cmUgZ2VuZXJhbGl6YWJpbGl0eS4KCgojIyMgUmFuZG9tIEZvcmVzdCBTY2F0dGVyIFBsb3QgCgpUaGUgb3V0cHV0IG9mIHRoZSBSYW5kb20gRm9yZXN0IG1vZGVsIGluZGljYXRlcyBwcm9taXNpbmcgY2hhcmFjdGVyaXN0aWNzLCB3aXRoIGEgbW9kZXJhdGUgcGVyY2VudGFnZSBvZiB2YXJpYW5jZSBleHBsYWluZWQgNTYuNjglIGFuZCBhIG1lYW4gc3F1YXJlZCByZXNpZHVhbCBvZiA3MC4xODQzMi4gVG8gZnVydGhlciBhc3Nlc3MgdGhlIG1vZGVsJ3MgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSwgYSBzY2F0dGVyIHBsb3Qgb2YgYWN0dWFsIHZzIHByZWRpY3RlZCB2YWx1ZXMgaXMgY3JlYXRlZC4gVGhpcyB2aXN1YWxpemF0aW9uIGFsbG93cyBmb3IgYSBkaXJlY3QgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIGFuZCB0aGUgdHJ1ZS1saWZlIGV4cGVjdGFuY3kgdmFsdWVzLgoKYGBge3IsZWNobz1GQUxTRX0KCiMgQ3JlYXRlIGEgc2NhdHRlciBwbG90IG9mIGFjdHVhbCB2cy4gcHJlZGljdGVkIHZhbHVlcyBmb3IgUmFuZG9tIEZvcmVzdCBtb2RlbApnZ3Bsb3QoZGF0YSA9IHRlc3RfZGF0YSwgYWVzKHggPSBMaWZlRXhwLCB5ID0gcHJlZGljdGlvbnNfcmYpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBsYWJzKHggPSAiQWN0dWFsIExpZmUgRXhwZWN0YW5jeSIsIHkgPSAiUHJlZGljdGVkIExpZmUgRXhwZWN0YW5jeSIsIAogICAgICAgdGl0bGUgPSAiQWN0dWFsIHZzLiBQcmVkaWN0ZWQgTGlmZSBFeHBlY3RhbmN5IChSYW5kb20gRm9yZXN0IE1vZGVsKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApUaGUgc2NhdHRlciBwbG90IHNob3djYXNlcyBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzIHdoZXJlIHRoZSB4LWF4aXMgcmVwcmVzZW50cyB0aGUgYWN0dWFsIGxpZmUgZXhwZWN0YW5jeSB2YWx1ZXMsIGFuZCB0aGUgeS1heGlzIHJlcHJlc2VudHMgdGhlIGNvcnJlc3BvbmRpbmcgcHJlZGljdGVkIHZhbHVlcyBnZW5lcmF0ZWQgYnkgdGhlIFJhbmRvbSBGb3Jlc3QgbW9kZWwuIEEgcmVkIGRhc2hlZCBsaW5lIGlzIG92ZXJsYWlkIG9uIHRoZSBwbG90LCBpbmRpY2F0aW5nIHRoZSBpZGVhbCBzY2VuYXJpbyB3aGVyZSBhY3R1YWwgYW5kIHByZWRpY3RlZCB2YWx1ZXMgcGVyZmVjdGx5IGFsaWduLgoKSW4gdGhpcyBjYXNlLCB0aGUgc2NhdHRlciBwbG90IHJldmVhbHMgYSBnZW5lcmFsbHkgbGluZWFyIHBhdHRlcm4sIHN1Z2dlc3RpbmcgdGhhdCB0aGUgUmFuZG9tIEZvcmVzdCBtb2RlbCBjYXB0dXJlcyB0aGUgdW5kZXJseWluZyByZWxhdGlvbnNoaXBzIGluIHRoZSBkYXRhLiBQb2ludHMgYXJlIGNsb3NlbHkgY2x1c3RlcmVkIGFyb3VuZCB0aGUgaWRlYWwgbGluZSwgaW5kaWNhdGluZyBhIHN0cm9uZyBjb3JyZXNwb25kZW5jZSBiZXR3ZWVuIHRoZSBwcmVkaWN0ZWQgYW5kIGFjdHVhbCBsaWZlIGV4cGVjdGFuY3kgdmFsdWVzLiBUaGlzIGFsaWdubWVudCBzaWduaWZpZXMgdGhhdCB0aGUgbW9kZWwgaXMgbWFraW5nIGFjY3VyYXRlIHByZWRpY3Rpb25zLCBhbmQgdGhlIGRldmlhdGlvbnMgZnJvbSB0aGUgaWRlYWwgbGluZSBhcmUgcmVsYXRpdmVseSBzbWFsbC4KCk92ZXJhbGwsIHRoZSBzY2F0dGVyIHBsb3QgdmlzdWFsbHkgcmVpbmZvcmNlcyB0aGUgbW9kZWwncyBlZmZlY3RpdmVuZXNzLCBzaG93Y2FzaW5nIGl0cyBhYmlsaXR5IHRvIHByb3ZpZGUgcmVsaWFibGUgcHJlZGljdGlvbnMgZm9yIGxpZmUgZXhwZWN0YW5jeSBiYXNlZCBvbiBHRFAgcGVyIGNhcGl0YS4gVGhlIHByb3hpbWl0eSBvZiB0aGUgcG9pbnRzIHRvIHRoZSBpZGVhbCBsaW5lIGluZGljYXRlcyBhIHN0cm9uZyBwcmVkaWN0aXZlIHJlbGF0aW9uc2hpcCwgc3VwcG9ydGluZyB0aGUgbW9kZWwncyB1dGlsaXR5IGluIHVuZGVyc3RhbmRpbmcgYW5kIGZvcmVjYXN0aW5nIGxpZmUgZXhwZWN0YW5jeSBwYXR0ZXJucy4KCgpJIHdpbGwgbGV2ZXJhZ2UgdGhlIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgYW5kIEdyYWRpZW50IEJvb3N0aW5nIGFsZ29yaXRobXMgdG8gY29tcGFyZSB0aGVpciBwZXJmb3JtYW5jZSB3aXRoIHRoZSBMaW5lYXIgUmVncmVzc2lvbiBhbmQgUmFuZG9tIEZvcmVzdCBtb2RlbHMuIFRoZSBvYmplY3RpdmUgaXMgdG8gZGlzY2VybiB3aGljaCBtb2RlbCB5aWVsZHMgdGhlIG1vc3QgYWNjdXJhdGUgcHJlZGljdGlvbnMgaW4gdGhlIGNvbnRleHQgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEuIEJ5IHN5c3RlbWF0aWNhbGx5IGV2YWx1YXRpbmcgdGhlc2UgZGl2ZXJzZSBhbGdvcml0aG1zLCBJIGFpbSB0byBkZXRlcm1pbmUgdGhlIG1vc3QgZWZmZWN0aXZlIGFwcHJvYWNoIGZvciBjYXB0dXJpbmcgdGhlIGludHJpY2F0ZSByZWxhdGlvbnNoaXAgYW5kIG1ha2luZyByZWxpYWJsZSBwcmVkaWN0aW9ucy4KClxuZXdwYWdlCgojIyBTdXBwb3J0IFZlY3RvciBNYWNoaW5lIFJlZ3Jlc3NvciBNb2RlbAoKQSBTdXBwb3J0IFZlY3RvciBNYWNoaW5lICBpcyBhIHN1cGVydmlzZWQgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdXNlZCBmb3IgY2xhc3NpZmljYXRpb24gYW5kIHJlZ3Jlc3Npb24gdGFza3MuIFRoZSBtYWluIGlkZWEgYmVoaW5kIFNWTSBpcyB0byBmaW5kIGEgaHlwZXJwbGFuZSB0aGF0IGJlc3Qgc2VwYXJhdGVzIHRoZSBkYXRhIGludG8gZGlmZmVyZW50IGNsYXNzZXMuIFRoZSBoeXBlcnBsYW5lIGNob3NlbiBpcyB0aGUgb25lIHRoYXQgbWF4aW1pemVzIHRoZSBtYXJnaW4sIHdoaWNoIGlzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBoeXBlcnBsYW5lIGFuZCB0aGUgbmVhcmVzdCBkYXRhIHBvaW50IGZyb20gZWFjaCBjbGFzcyBAZW53aWtpOjExODY3ODYyODAuCgpUaGUgZXF1YXRpb24gb2YgYSBsaW5lYXIgU3VwcG9ydCBWZWN0b3IgTWFjaGluZSBpcyBhcyBmb2xsb3dzOgoKJCQKZihcbWF0aGJme3h9KSA9IFx0ZXh0e3NpZ259KFxtYXRoYmZ7d30gXGNkb3QgXG1hdGhiZnt4fSArIGIpIFxcCiQkCgokJApcYmVnaW57YWxpZ24qfQogICAgXHRleHR7V2hlcmU6fSBcXAogICAgZihcbWF0aGJme3h9KSAmIFx0ZXh0eyBpcyB0aGUgZGVjaXNpb24gZnVuY3Rpb24ufSBcXAogICAgXG1hdGhiZnt3fSAmIFx0ZXh0eyBpcyB0aGUgd2VpZ2h0IHZlY3Rvci59IFxcCiAgICBcbWF0aGJme3h9ICYgXHRleHR7IGlzIHRoZSBpbnB1dCB2ZWN0b3IufSBcXAogICAgYiAmIFx0ZXh0eyBpcyB0aGUgYmlhcyB0ZXJtLn0KXGVuZHthbGlnbip9CiQkCgokJApcdGV4dHtUaGUgb3B0aW1pemF0aW9uIHByb2JsZW0gYXNzb2NpYXRlZCB3aXRoIFNWTSBjYW4gYmUgcmVwcmVzZW50ZWQgYXMgfVxcCiQkCgokJApcdGV4dHtNaW5pbWl6ZTogfSBcZnJhY3sxfXsyfVx8XG1hdGhiZnt3fVx8XjJcXAokJAoKJCQKXHRleHR7U3ViamVjdCB0byB0aGUgY29uc3RyYWludHM6fVxcCnlfaShcbWF0aGJme3d9IFxjZG90IFxtYXRoYmZ7eH1faSArIGIpIFxnZXEgMSBcdGV4dHsgZm9yIH0gaSA9IDEsIDIsIFxsZG90cywgTgokJAogCgoKCmBgYHtyLGVjaG89RkFMU0V9CgojIExvYWQgdGhlIG5lY2Vzc2FyeSBsaWJyYXJ5CmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZTEwNzEiLCBxdWlldGx5ID0gVFJVRSkpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJlMTA3MSIpCn0KIyBCdWlsZCBhIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgUmVncmVzc29yIG1vZGVsCnN2bV9tb2RlbCA8LSBlMTA3MTo6c3ZtKExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CnRlc3RfZGF0YSRwcmVkaWN0aW9uc19zdm0gPC0gcHJlZGljdChzdm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEpCgojIENhbGN1bGF0ZSBSLXNxdWFyZWQgc2NvcmUgZm9yIFNWTQpzdm1fcl9zcXVhcmVkIDwtIDEgLSBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gdGVzdF9kYXRhJHByZWRpY3Rpb25zX3N2bSleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpCgpwcmludChwYXN0ZSgiU1ZNIFItc3F1YXJlZCBTY29yZTogIiwgcm91bmQoc3ZtX3Jfc3F1YXJlZCwgMikpKQoKIyBCdWlsZCBhIFN1cHBvcnQgVmVjdG9yIE1hY2hpbmUgUmVncmVzc29yIG1vZGVsCiNzdm1fbW9kZWwgPC0gc3ZtKExpZmVFeHAgfiBnZHBfcGVyX2NhcGl0YSwgZGF0YSA9IHRyYWluX2RhdGEpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CiN0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtIDwtIHByZWRpY3Qoc3ZtX21vZGVsLCBuZXdkYXRhID0gdGVzdF9kYXRhKQoKIyBDYWxjdWxhdGUgUi1zcXVhcmVkIHNjb3JlIGZvciBTVk0KI3N2bV9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSAjbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpCgojcHJpbnQocGFzdGUoIlNWTSBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKHN2bV9yX3NxdWFyZWQsIDIpKSkKCmBgYAoKIyMgR3JhZGllbnQgQm9vc3RpbmcgUmVncmVzc29yIE1vZGVsCgpHcmFkaWVudCBCb29zdGluZyBpcyBhbiBlbnNlbWJsZSBsZWFybmluZyB0ZWNobmlxdWUgdXNlZCBmb3IgYm90aCByZWdyZXNzaW9uIGFuZCBjbGFzc2lmaWNhdGlvbiB0YXNrcy4gVGhlIGFsZ29yaXRobSBidWlsZHMgYSBzZXJpZXMgb2Ygd2VhayBsZWFybmVycywgdHlwaWNhbGx5IGRlY2lzaW9uIHRyZWVzLCBhbmQgY29tYmluZXMgdGhlbSB0byBjcmVhdGUgYSBzdHJvbmcgbGVhcm5lci4gR3JhZGllbnQgQm9vc3RpbmcgZm9jdXNlcyBvbiBtaW5pbWl6aW5nIHRoZSBlcnJvcnMgb2YgdGhlIHByZXZpb3VzIG1vZGVscyBieSBhZGRpbmcgbmV3IG1vZGVscyB0aGF0IGNvcnJlY3QgdGhlIG1pc3Rha2VzIG9mIHRoZSBleGlzdGluZyBvbmVzIEBlbndpa2k6MTE3NzI1ODkxMy4KCiQkCkZfbSh4KSA9IEZfe20tMX0oeCkgKyBcbnUgaF9tKHgpCiQkCgokJApcdGV4dHt3aGVyZTp9IFxcCiAgICBGX20oeCkgXHRleHR7IGlzIHRoZSBtb2RlbCBhdCBpdGVyYXRpb24gfSBtIFxcCiAgICBGX3ttLTF9KHgpIFx0ZXh0eyBpcyB0aGUgbW9kZWwgZnJvbSB0aGUgcHJldmlvdXMgaXRlcmF0aW9ufSBcXAogICAgXG51IFx0ZXh0eyBpcyB0aGUgbGVhcm5pbmcgcmF0ZSwgYSBoeXBlcnBhcmFtZXRlciBpbiB0aGUgcmFuZ2UgKDAsIDEpfSBcXAogICAgaF9tKHgpIFx0ZXh0eyBpcyB0aGUgd2VhayBsZWFybmVyIChlLmcuLCBhIGRlY2lzaW9uIHRyZWUpIHRyYWluZWQgdG8gY29ycmVjdCB0aGUgcmVzaWR1YWxzfSBcXAokJAoKCmBgYHtyLGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQoKIyBMb2FkIHRoZSBuZWNlc3NhcnkgbGlicmFyeQppbnN0YWxsLnBhY2thZ2VzKCJnYm0iKQpsaWJyYXJ5KGdibSkKCiMgQnVpbGQgYSBHcmFkaWVudCBCb29zdGluZyBSZWdyZXNzb3IgbW9kZWwKZ2JtX21vZGVsIDwtIGdibShMaWZlRXhwIH4gZ2RwX3Blcl9jYXBpdGEsIGRhdGEgPSB0cmFpbl9kYXRhLCBuLnRyZWVzID0gMTAwLCBpbnRlcmFjdGlvbi5kZXB0aCA9IDMpCgojIE1ha2UgcHJlZGljdGlvbnMgb24gdGhlIHRlc3Qgc2V0CnRlc3RfZGF0YSRwcmVkaWN0aW9uc19nYm0gPC0gcHJlZGljdChnYm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEsIG4udHJlZXMgPSAxMDApCgojIENhbGN1bGF0ZSBSLXNxdWFyZWQgc2NvcmUgZm9yIEdyYWRpZW50IEJvb3N0aW5nCmdibV9yX3NxdWFyZWQgPC0gMSAtIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfZ2JtKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSBtZWFuKHRlc3RfZGF0YSRMaWZlRXhwKSleMikKCnByaW50KHBhc3RlKCJHcmFkaWVudCBCb29zdGluZyBSLXNxdWFyZWQgU2NvcmU6ICIsIHJvdW5kKGdibV9yX3NxdWFyZWQsIDIpKSkKCmBgYApcbmV3cGFnZQoKIyBNb2RlbCBFdmFsdWF0aW9uIAoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KIyBDYWxjdWxhdGUgUk1TRSBmb3IgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwKbG1fcm1zZSA8LSBzcXJ0KG1lYW4oKHRlc3RfZGF0YSRMaWZlRXhwIC0gcHJlZGljdChsbV9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkpXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgUmFuZG9tIEZvcmVzdApyZl9ybXNlIDwtIHNxcnQobWVhbigodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgR3JhZGllbnQgQm9vc3RpbmcKZ2JtX3Jtc2UgPC0gc3FydChtZWFuKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9uc19nYm0pXjIpKQoKIyBDYWxjdWxhdGUgUk1TRSBmb3IgU1ZNCnN2bV9ybXNlIDwtIHNxcnQobWVhbigodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfc3ZtKV4yKSkKCiMgUHJpbnQgUk1TRSB2YWx1ZXMKcHJpbnQocGFzdGUoIkxpbmVhciBSZWdyZXNzaW9uIFJNU0U6ICIsIHJvdW5kKGxtX3Jtc2UsIDIpKSkKcHJpbnQocGFzdGUoIlJhbmRvbSBGb3Jlc3QgUk1TRTogIiwgcm91bmQocmZfcm1zZSwgMikpKQpwcmludChwYXN0ZSgiR3JhZGllbnQgQm9vc3RpbmcgUk1TRTogIiwgcm91bmQoZ2JtX3Jtc2UsIDIpKSkKcHJpbnQocGFzdGUoIlNWTSBSTVNFOiAiLCByb3VuZChzdm1fcm1zZSwgMikpKQoKYGBgCgojIyBSTVNFIENvbXBhcmlzb24gb2YgUmVncmVzc2lvbiBNb2RlbHMKClJvb3QgTWVhbiBTcXVhcmVkIEVycm9yIGlzIGEgbWV0cmljIHVzZWQgdG8gZXZhbHVhdGUgdGhlIGFjY3VyYWN5IG9mIGEgcmVncmVzc2lvbiBtb2RlbCwgaXQgcHJvdmlkZXMgYSBtZWFzdXJlIG9mIGhvdyB3ZWxsIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIG1hdGNoIHRoZSBhY3R1YWwgb2JzZXJ2ZWQgdmFsdWVzLiBSTVNFIG1lYXN1cmVzIHRoZSBhdmVyYWdlIG1hZ25pdHVkZSBvZiB0aGUgZXJyb3JzIGJldHdlZW4gcHJlZGljdGVkIGFuZCBhY3R1YWwgdmFsdWVzIGFuZCBpdCBwZW5hbGl6ZXMgbGFyZ2VyIGVycm9ycyBtb3JlIGhlYXZpbHkgdGhhbiBzbWFsbGVyIG9uZXMuCmBgYHtyLGVjaG89RkFMU0V9CgojIENyZWF0ZSBhIGJhciBjaGFydCB0byBjb21wYXJlIFJNU0UgdmFsdWVzCm1vZGVsX25hbWVzIDwtIGMoIkxpbmVhciBSZWdyZXNzaW9uIiwgIlJhbmRvbSBGb3Jlc3QiLCAiR3JhZGllbnQgQm9vc3RpbmciLCAiU1ZNIikKcm1zZV92YWx1ZXMgPC0gYyhsbV9ybXNlLCByZl9ybXNlLCBnYm1fcm1zZSwgc3ZtX3Jtc2UpCgpiYXJwbG90KHJtc2VfdmFsdWVzLCBuYW1lcy5hcmcgPSBtb2RlbF9uYW1lcywgY29sID0gInNreWJsdWUiLCAKICAgICAgICBtYWluID0gIlJNU0UgQ29tcGFyaXNvbiBvZiBSZWdyZXNzaW9uIE1vZGVscyIsCiAgICAgICAgeWxhYiA9ICJSb290IE1lYW4gU3F1YXJlZCBFcnJvciAoUk1TRSkiLCB5bGltID0gYygwLCBtYXgocm1zZV92YWx1ZXMpICsgNSkpCgpgYGAKVXN1YWxseSwgYSBsb3dlciBSTVNFIHZhbHVlIGluZGljYXRlcyBiZXR0ZXIgbW9kZWwgcGVyZm9ybWFuY2UsIGFzIGl0IG1lYW5zIHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIGFyZSBjbG9zZXIgdG8gdGhlIGFjdHVhbCB2YWx1ZXMuIFRoZXJlZm9yZSwgYmFzZWQgb24gdGhlIGFib3ZlIHJlc3VsdHMsIHRoZSBHcmFkaWVudCBCb29zdGluZyBtb2RlbCBzZWVtcyB0byBwZXJmb3JtIHRoZSBiZXN0IGFtb25nIHRoZSBtb2RlbHMsIGZvbGxvd2VkIGNsb3NlbHkgYnkgdGhlIFNWTSBtb2RlbCwgdGhlbiB0aGUgUmFuZG9tIEZvcmVzdCwgYW5kIGZpbmFsbHkgTGluZWFyIFJlZ3Jlc3Npb24uCmBgYHtyLGVjaG89RkFMU0UscmVzdWx0cz0naGlkZSd9CnIyX2xtIDwtIDEgLSAoc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9ucyleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpKQpyMl9yZiA8LSAxIC0gKHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSB0ZXN0X2RhdGEkcHJlZGljdGlvbnNfcmYpXjIpIC8gc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIG1lYW4odGVzdF9kYXRhJExpZmVFeHApKV4yKSkKcjJfZ2JtIDwtIDEgLSAoc3VtKCh0ZXN0X2RhdGEkTGlmZUV4cCAtIHRlc3RfZGF0YSRwcmVkaWN0aW9ucyleMikgLyBzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gbWVhbih0ZXN0X2RhdGEkTGlmZUV4cCkpXjIpKQpyMl9zdm0gPC0gMSAtIChzdW0oKHRlc3RfZGF0YSRMaWZlRXhwIC0gdGVzdF9kYXRhJHByZWRpY3Rpb25zX3JmKV4yKSAvIHN1bSgodGVzdF9kYXRhJExpZmVFeHAgLSBtZWFuKHRlc3RfZGF0YSRMaWZlRXhwKSleMikpCgoKYGBgClxuZXdwYWdlCgojIyBSLVNxdWFyZWQgQ29tcGFyaXNvbiBvZiBSZWdyZXNzaW9uIE1vZGVscwoKVGhlIFItc3F1YXJlZCBpcyBhIHN0YXRpc3RpY2FsIG1lYXN1cmUgb2YgaG93IHdlbGwgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyBpbiBhIHJlZ3Jlc3Npb24gbW9kZWwgZXhwbGFpbiB0aGUgdmFyaWFiaWxpdHkgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gSXQgaXMgYSBzY2FsZSBmcm9tIDAgdG8gMS4gd2hlcmU6CjAgaW5kaWNhdGVzIHRoYXQgdGhlIG1vZGVsIGRvZXMgbm90IGV4cGxhaW4gYW55IG9mIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLgoxIGluZGljYXRlcyB0aGF0IHRoZSBtb2RlbCBleHBsYWlucyBhbGwgb2YgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuCmBgYHtyLCBlY2hvPUZBTFNFfQojIENyZWF0ZSBhIGJhciBjaGFydCB0byBjb21wYXJlIFItc3F1YXJlZCB2YWx1ZXMKbW9kZWxfbmFtZXMgPC0gYygiTGluZWFyIFJlZ3Jlc3Npb24iLCAiUmFuZG9tIEZvcmVzdCIsICJHcmFkaWVudCBCb29zdGluZyIsICJTVk0iKQpyX3NxdWFyZWRfdmFsdWVzIDwtIGMobG1fcl9zcXVhcmVkLCByZl9yX3NxdWFyZWQsIGdibV9yX3NxdWFyZWQsIHN2bV9yX3NxdWFyZWQpCgpiYXJwbG90KHJfc3F1YXJlZF92YWx1ZXMsIG5hbWVzLmFyZyA9IG1vZGVsX25hbWVzLCBjb2wgPSAibGlnaHRncmVlbiIsIAogICAgICAgIG1haW4gPSAiUi1TcXVhcmVkIENvbXBhcmlzb24gb2YgUmVncmVzc2lvbiBNb2RlbHMiLAogICAgICAgIHlsYWIgPSAiUi1TcXVhcmVkIiwgeWxpbSA9IGMoMCwgbWF4KHJfc3F1YXJlZF92YWx1ZXMpICsgMC4yKSkKCiMgQWRkIHZhbHVlcyBvbiB0b3Agb2YgdGhlIGJhcnMKdGV4dCgxOjQsIHJfc3F1YXJlZF92YWx1ZXMgKyAwLjA1LCByb3VuZChyX3NxdWFyZWRfdmFsdWVzLCAyKSwgcG9zID0gMywgY2V4ID0gMS4zLCBjb2wgPSAiYmxhY2siKQoKYGBgIApSLXNxdWFyZWQgdmFsdWUgb2YgMC42OCBpbmRpY2F0ZXMgdGhhdCB0aGUgR3JhZGllbnQgQm9vc3RpbmcgbW9kZWwgaXMgcmVhc29uYWJseSBlZmZlY3RpdmUgYXQgZXhwbGFpbmluZyB0aGUgdmFyaWF0aW9uIGluIHRoZSB0YXJnZXQgdmFyaWFibGUuIEhvd2V2ZXIsIGl0J3MgY3J1Y2lhbCB0byBjb25zaWRlciBvdGhlciBhc3BlY3RzIG9mIG1vZGVsIGV2YWx1YXRpb24gYW5kIHRoZSBzcGVjaWZpYyBnb2FscyBvZiB0aGlzIHByb2plY3QuIAoKIyBMaW1pdGF0aW9ucyAKVGhlIHByb2plY3QgcmVsaWVzIG9uIGF2YWlsYWJsZSBkYXRhLCBhbmQgYW55IGdhcHMgb3IgaW5hY2N1cmFjaWVzIGluIHRoZSBkYXRhIGNvdWxkIGltcGFjdCB0aGUgcmVzdWx0cy4gVGhlIG1vZGVscyB1c2VkIG1ha2UgY2VydGFpbiBhc3N1bXB0aW9ucywgYW5kIHRoZSByZWFsLXdvcmxkIHJlbGF0aW9uc2hpcCBpcyBsaWtlbHkgaW5mbHVlbmNlZCBieSBudW1lcm91cyBjb21wbGV4IGZhY3RvcnMuIFdoaWxlIHRoZSBwcm9qZWN0IGV4cGxvcmVzIGNvcnJlbGF0aW9ucywgZXN0YWJsaXNoaW5nIGNhdXNhdGlvbiByZXF1aXJlcyBtb3JlIGluLWRlcHRoIHN0dWRpZXMgYW5kIGNvbnNpZGVyYXRpb25zIG9mIGNvbmZvdW5kaW5nIHZhcmlhYmxlcy4KCiMgRnVydGhlciBBbmFseXNpcyBBcmVhcwpUbyBjb25kdWN0IGEgbW9yZSBleHRlbnNpdmUgYW5hbHlzaXMsIHNvbWVvbmUgY2FuIGV4cGxvcmUgaG93IHRoZSByZWxhdGlvbnNoaXAgZXZvbHZlcyBvdmVyIHRpbWUgYnkgaW5jb3Jwb3JhdGluZyBkYXRhIGZyb20gYWRkaXRpb25hbCB5ZWFycy4gRm9yIGEgZGV0YWlsZWQgcmVnaW9uYWwgYW5hbHlzaXMsIGl0IHdvdWxkIGJlIGJlbmVmaWNpYWwgdG8gY29uZHVjdCBhIG1vcmUgZ3JhbnVsYXIgZXhhbWluYXRpb24gb2Ygc3BlY2lmaWMgcmVnaW9ucywgaW4gb3JkZXIgIHRvIHVuY292ZXIgcmVnaW9uYWwgdmFyaWF0aW9ucyBhbmQgdHJlbmRzLiBBZGRpdGlvbmFsbHksIGludmVzdGlnYXRpbmcgc3VwcGxlbWVudGFyeSBmYWN0b3JzIHN1Y2ggYXMgaGVhbHRoY2FyZSBpbmZyYXN0cnVjdHVyZSwgZWR1Y2F0aW9uLCBhbmQgc29jaWFsIHBvbGljaWVzIGNvdWxkIHByb3ZpZGUgaW5zaWdodHMgaW50byB0aGVpciBjb250cmlidXRpb25zIHRvIGxpZmUgZXhwZWN0YW5jeS4KCiMgQ29uY2x1c2lvbnMKVGhpcyBwcm9qZWN0IGhhcyB1bmRlcnRha2VuIGEgdGhvcm91Z2ggaW52ZXN0aWdhdGlvbiBpbnRvIHRoZSBjb21wbGV4IGludGVycGxheSBiZXR3ZWVuIGxpZmUgZXhwZWN0YW5jeSBhbmQgR0RQIHBlciBjYXBpdGEsIGxldmVyYWdpbmcgYSBkaXZlcnNlIHNldCBvZiBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBhbmQgYWxnb3JpdGhtcy4gVGhlIGFuYWx5c2lzIHVuZWFydGhlZCBpbnRyaWNhdGUgcGF0dGVybnMgYW5kIGNvbXBsZXhpdGllcyBpbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgdmFyaWFibGVzLiBOb3RhYmx5LCBvdXIga2V5IGZpbmRpbmdzIGlsbHVtaW5hdGUgdGhlIGxvZ2FyaXRobWljIG5hdHVyZSBvZiB0aGlzIHJlbGF0aW9uc2hpcCwgcmV2ZWFsaW5nIHRoYXQgdGhlIGluZmx1ZW5jZSBvZiBHRFAgcGVyIGNhcGl0YSBvbiBsaWZlIGV4cGVjdGFuY3kgZXhoaWJpdHMgdmFyaWF0aW9ucyBhY3Jvc3MgZGlmZmVyZW50IGVjb25vbWljIGNvbnRleHRzLgoKVGhlIHJlc3VsdHMgb2YgdGhpcyBwcm9qZWN0IHByb3ZpZGUgdmFsdWFibGUgaW5zaWdodHMgaW50byB1bmRlcnN0YW5kaW5nIGhvdyBlY29ub21pYyBwcm9zcGVyaXR5IGFuZCBsaWZlIGV4cGVjdGFuY3kgYXJlIGxpbmtlZCBnbG9iYWxseS4gQnkgYWNrbm93bGVkZ2luZyBhbmQgZW1icmFjaW5nIHRoZSBzdWJ0bGUgY29tcGxleGl0aWVzIGluIHRoZXNlIGNvbm5lY3Rpb25zLCBteSByZXNlYXJjaCBsYXlzIHRoZSBncm91bmR3b3JrIGZvciBtb3JlIGluZm9ybWVkIGFuZCB0YWlsb3JlZCBzdHJhdGVnaWVzLiBGdXJ0aGVyIGFuYWx5c2VzIGFuZCBjYXJlZnVsIGNvbnNpZGVyYXRpb25zIHdpbGwgdW5kb3VidGVkbHkgcmVmaW5lIG91ciB1bmRlcnN0YW5kaW5nLCBndWlkaW5nIHRoZSBkZXZlbG9wbWVudCBvZiBjb21wcmVoZW5zaXZlIGFwcHJvYWNoZXMgdG8gdGFja2xlIHVyZ2VudCBjaGFsbGVuZ2VzIGluIHB1YmxpYyBoZWFsdGggYW5kIHNvY2lvLWVjb25vbWljIGRvbWFpbnMuCgoKCgoKXG5ld3BhZ2UKCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL0Y0RkxvZ28ucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKIyAqKkZvcmVjYXN0aW5nIG9mIFBldCBGb29kcyBEZW1hbmQgIFVzaW5nIFRpbWUgU2VyaWVzIEFuYWx5c2lzIHRvIEVuaGFuY2UgU3RyYXRlZ2ljIFRlY2huaXF1ZXMgYW5kIFJlc291cmNlIEFsbG9jYXRpb24gZm9yIGEgTm9uLXByb2ZpdCBPcmdhbml6YXRpb24qKgoKCgoKIyBCYWNrZ3JvdW5kCgpGcmllbmRzIGZvciBMaWZlIGlzIGEgSG91c3Rvbi1iYXNlZCBub25wcm9maXQgb3JnYW5pemF0aW9uIHRoYXQgcHJvdmlkZXMgc2VydmljZXMgdG8gcGV0IG93bmVycyBpbiBuZWVkIHRocm91Z2hvdXQgdGhlIEdyZWF0ZXIgSG91c3RvbiBjb21tdW5pdHkuICBGb3VuZGVkIGluIDIwMDEsIEZyaWVuZHMgZm9yIExpZmUgaGFzIGJlZW4gYSBkZWRpY2F0ZWQgZm9yY2UgaW4gc2VydmluZyBwZXRzIGFjcm9zcyBHcmVhdGVyIEhvdXN0b24uIEluaXRpYWxseSBjb25jZWl2ZWQgYXMgYW4gYW5pbWFsIHNoZWx0ZXIsIHRoZSBvcmdhbml6YXRpb24ncyBwcmltYXJ5IGNvbW1pdG1lbnQgbGllcyBpbiBlbnN1cmluZyB0aGUgc2FmZXR5IGFuZCB3ZWxsLWJlaW5nIG9mIGFuaW1hbHMsIGZvc3RlcmluZyBlbmR1cmluZyBjb25uZWN0aW9ucyB3aXRoIHRoZSBodW1hbnMgd2hvIGNoZXJpc2ggdGhlbS4gQmV5b25kIGVzdGFibGlzaGluZyB0aGUgY2l0eSdzIGZpcnN0IG5vLWtpbGwgc2hlbHRlciwgRnJpZW5kcyBmb3IgTGlmZSBhY3RpdmVseSBlbmdhZ2VzIGluIHBldCBhZG9wdGlvbiBpbml0aWF0aXZlcyBhbmQgcHJvdmlkZXMgZXNzZW50aWFsIG1lZGljYWwgc3VwcG9ydCBmb3IgYW5pbWFscy4KCkRyaXZlbiBieSBhIHBhc3Npb24gZm9yIGluc3RpZ2F0aW5nIHN5c3RlbWljIGNoYW5nZSBmb3IgdGhlIGJldHRlcm1lbnQgb2YgYW5pbWFsIGxpdmVzLCB0aGUgb3JnYW5pemF0aW9uIGhhcyBldm9sdmVkIHRvIGFkZHJlc3MgdmFyaW91cyBmYWNldHMgb2YgcGV0IHdlbGZhcmUuIEluIHJlY29nbml0aW9uIG9mIHRoZSB3aWRlc3ByZWFkIGltcGFjdCBvZiBmb29kIGluc2VjdXJpdHksIEZyaWVuZHMgZm9yIExpZmUgaGFzIHRob3VnaHRmdWxseSBpbnRyb2R1Y2VkIGEgcGV0IGZvb2QgYmFuayBmb3IgcGV0IG93bmVycyBmYWNpbmcgZWNvbm9taWMgY2hhbGxlbmdlcy4gRXZlcnkgeWVhciwgdGhleSBnZW5lcm91c2x5IGRpc3RyaWJ1dGUgc3Vic3RhbnRpYWwgYW1vdW50cyBvZiBwZXQgZm9vZCwgbWFraW5nIGEgdGFuZ2libGUgZGlmZmVyZW5jZSBpbiB0aGUgbGl2ZXMgb2YgcGV0cyBhbmQgdGhlaXIgb3duZXJzLiBUaGlzIHByb2plY3QgZGVsdmVzIGludG8gdGhlIGhlYXJ0IG9mIHRoZWlyIGltcGFjdGZ1bCB3b3JrIGluIHRoZSByZWFsbSBvZiBwZXQgZm9vZCBkaXN0cmlidXRpb24uCgpUaGUgb3JnYW5pemF0aW9uIHJlY29nbml6ZXMgdGhhdCB0aGVpciBjdXJyZW50IGhlYWRxdWFydGVycyBsb2NhdGlvbiBkb2VzIG5vdCBuZWNlc3NhcmlseSByZWZsZWN0IHRoZSBsb3dlciBzb2Npb2Vjb25vbWljIGFyZWFzIHdoZXJlIHRoZXJlIGlzIGEgZ3JlYXRlciBuZWVkIGZvciB0aGVpciBwZXQgZm9vZCBzZXJ2aWNlcy4gVGhleSB3YW50IHRvIGxldmVyYWdlIGludGVybmFsIGRhdGEgdG8gaGVscCB1bmNvdmVyIGRpc2NyZXBhbmNpZXMgaW4gaGlnaGVyIG5lZWQgY29tbXVuaXRpZXMgYW5kIGV4cGFuZCB0aGVpciBvdXRyZWFjaC4gT3ZlciB0aGUgeWVhcnMsIEZyaWVuZHMgZm9yIExpZmUgaGFzIGNvbGxlY3RlZCBkYXRhIG9uIHRoZWlyIHBldCBmb29kIGJhbmsgdXNhZ2UgYW5kIGludmVudG9yeS4gSG93ZXZlciwgdGhlIGRhdGEgaGF2ZSBub3QgYmVlbiBhc3NlbWJsZWQsIGNsZWFuZWQsIGV4dHJhY3RlZCwgYW5kIGFuYWx5emVkIHRvIHRoZWlyIGZ1bGwgcG90ZW50aWFsLiBbaGVyZSBpcyB0aGUgd2Vic2l0ZSBvZiB0aGUgb3JnYW5pemF0aW9uXSAoaHR0cHM6Ly9mcmllbmRzNGxpZmUub3JnKQoKVGhlIG1haW4gb2JqZWN0aXZlIG9mIHRoaXMgcHJvamVjdCBpcyB0byBwcm92aWRlIHRlY2huaWNhbCBtZWFucyBmb3IgRnJpZW5kcyBmb3IgTGlmZSB0byBlZmZpY2llbnRseSBsZXZlcmFnZSBhbmQgdW5kZXJzdGFuZCBkYXRhIHRoYXQgYXJlIGNyaXRpY2FsIHRvIGl0cyBmdXR1cmUgZnVuZHJhaXNpbmcgYW5kIG91dHJlYWNoIGVmZm9ydHMuIFRoaXMgaW5jbHVkZXM6W1ByZXZpb3VzIFByb2plY3QgTGlua10oaHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2RyaXZlL2ZvbGRlcnMvMXNrTEVTRHdaN0o1QjItWnVKTGF2bGNRSXRrOUdiUVdQKSAKCiogRGV2ZWxvcCBhIGNlbnRyYWwgZGFzaGJvYXJkIHRoYXQgd2lsbCBjYXB0dXJlLCBhZ2dyZWdhdGUsIGFuYWx5emUsIHZpc3VhbGl6ZSwgYW5kIGZvcmVjYXN0IGRhdGEgdGhhdCB0aGUgbm9ucHJvZml0IGNhbiBpZGVudGlmeSBib3RoIHRoZWlyIGhpc3RvcmljYWwgZGlzdHJpYnV0aW9uLCBpbmNyZWFzZSBvdXRyZWFjaCBpbiBoaWdoLW5lZWQgY29tbXVuaXRpZXMgYW5kIGxldmVyYWdlIHRvIGRpcmVjdGx5IHN1cHBvcnQgZnVuZHJhaXNpbmcuCgoqCVRoZSBhcHBsaWNhdGlvbiBvZiB0aW1lIHNlcmllcyBhbmFseXNpcyB0ZWNobmlxdWVzIGZhY2lsaXRhdGVzIHRoZSBhY2N1cmF0ZSBmb3JlY2FzdGluZyBvZiBtb250aGx5IGRlbWFuZCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcywgcHJvdmlkaW5nIHRoZSBvcmdhbml6YXRpb24gd2l0aCB2YWx1YWJsZSBpbnNpZ2h0cyB0byBlbmhhbmNlIHRoZSBlZmZpY2llbmN5IG9mIG1hbmFnaW5nIGl0cyBwZXQgZm9vZCBiYW5rLgoKKglJbnRlZ3JhdGlvbiBvZiBkYXRhIGludG8gYSBNeVNRTCBkYXRhYmFzZSwgY29tcGxlbWVudGVkIGJ5IHByZWNpc2UgcXVlcmllcywgZW5oYW5jZXMgdGhlIGNhcGFiaWxpdHkgZm9yIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbnMgYW5kIG9wdGltaXppbmcgcmVzb3VyY2UgYWxsb2NhdGlvbi4KClRoZSBwdXJwb3NlIG9mIHRoaXMgcHJvamVjdCBpcyB0bzogCgoqIEVmZmljaWVudGx5IHByb2Nlc3MgaW5zaWdodHMgZnJvbSBwZXQgZm9vZCBiYW5rIGRhdGEKCioJQWdncmVnYXRlLCB2aXN1YWxpemUsICYgZW5hYmxlIGRhdGEgZm9yZWNhc3RpbmcgdG8gc3VwcG9ydCBwbGFubmluZyAmIGZ1bmRpbmcKCioJTG9jYXRlIGhpZ2gtbmVlZCBjb21tdW5pdGllcyB0byBkaXJlY3QgdGhlaXIgb3V0cmVhY2gKCioJSWRlbnRpZnkgMy01IHVuZGVyc2VydmVkIHppcCBjb2RlIGFyZWFzIHdpdGggaGlnaCBwZXQgZm9vZCBuZWVkcwoKKglTdXBwb3J0IGZ1dHVyZSBpbnZlbnRvcnksIGNhbXBhaWduIHBsYW5uaW5nICYgZnVuZHJhaXNpbmcuCgojIERhdGEKCkhhbmRsaW5nIHRoZSBkYXRhIHBvc2VkIGEgc2lnbmlmaWNhbnQgY2hhbGxlbmdlLiBVcG9uIHJlY2VpdmluZyB0aGUgRnJpZW5kcyBmb3IgTGlmZSBkYXRhc2V0LCB3ZSBmYWNlZCB2YXJpb3VzIGlzc3VlcywgaW5jbHVkaW5nIGluY29ycmVjdCBhbmQgbWlzc2luZyB6aXAgY29kZXMgaW4gdGhlIGFkZHJlc3NlcywgdW5jbGVhciBwZXQgdHlwZSBlbnRyaWVzLCBhbmQgbnVtZXJvdXMgY2VsbHMgcmVxdWlyaW5nIGNsZWFuaW5nLiBBZGRyZXNzaW5nIHRoZXNlIGlzc3VlcyByZXF1aXJlZCBjb25zaWRlcmFibGUgZWZmb3J0LCBlc3BlY2lhbGx5IGluIGNvcnJlY3RpbmcgemlwIGNvZGVzIGZvciBlYWNoIGFkZHJlc3MuIFRoaXMgcHJvY2VzcyBpbnZvbHZlZCB0aG9yb3VnaCB2ZXJpZmljYXRpb24gdG8gZ3VhcmFudGVlIGRhdGEgYWNjdXJhY3ksIHN1YnN0YW50aWFsbHkgYWRkaW5nIHRvIHRoZSB0aW1lIGRlZGljYXRlZCB0byBkYXRhIGNsZWFuaW5nIGFuZCB2YWxpZGF0aW9uLiBUaGUgZm9sbG93aW5nIHR3byBmaWd1cmVzIGlsbHVzdHJhdGluZyBpbnN0YW5jZXMgb2YgbWlzc2luZyBhbmQgaW5jb3JyZWN0IHppcCBjb2RlcywgYWxvbmcgd2l0aCB0aGUgbWV0aG9kIHVzZWQgdG8gcmVjdGlmeSBhbWJpZ3VvdXMgcGV0IHR5cGUgZW50cmllcy4KCmBgYHtyLCBlY2hvPUZBTFNFLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9Mywgb3V0LndpZHRoPSI1MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL0RhdGEyLnBuZyIsIGVycm9yID0gRkFMU0UpCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvRGF0YTEucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKCkZyb20gdGhlIGRhdGEgcHJlc2VudGVkIGFib3ZlLCBpdCdzIGFwcGFyZW50IHRoYXQgdGhlcmUgaXMgYSBtaXNtYXRjaCBiZXR3ZWVuIGFkZHJlc3NlcyBhbmQgemlwIGNvZGVzIGluIHRoZSBvcmFuZ2UtY29sb3JlZCBjZWxscywgZXZlbiB0aG91Z2ggdGhlIHN0cmVldCBhZGRyZXNzZXMgYXJlIHRoZSBzYW1lLlRoZSBjb3JyZWN0ZWQgemlwIGNvZGVzIHNob3djYXNlIGEgc2lnbmlmaWNhbnQgZWZmb3J0IGRlZGljYXRlZCB0byBvcmdhbml6aW5nIHRoZSBhZGRyZXNzIGFuZCB6aXAgY29kZSBjb2x1bW5zLCB3aXRoIGEgMTAwJSBhY2N1cmFjeSByYXRlIGFjcm9zcyBhbG1vc3QgZm91ciB0aG91c2FuZCBjZWxscy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjUwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvRGF0YTMucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKVGhlIGltYWdlIGFib3ZlIGhpZ2hsaWdodHMgYSBtaXNzcGVsbGluZyBpbiB0aGUgUGV0cyBjb2x1bW4gcmVzdWx0aW5nIGZyb20gc2V2ZXJhbCB0eXBvLiBUbyByZXNvbHZlIHRoaXMgaXNzdWUsIHdlIGVtcGxveWVkIGNvcnJlY3RpdmUgbWVhc3VyZXMgdXNpbmcgUiBjb2RlIHRvIHJlY3RpZnkgYWxsIGVudHJpZXMgaW4gdGhlIFBldHMgY29sdW1uLgoKIyBDZW50cmFsIERhc2hib2FyZCAgCgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9EYXNoYm9hcmQucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYApVdGlsaXppbmcgVGFibGVhdSwgSSBkZXNpZ25lZCBhIGNvbXByZWhlbnNpdmUgZGFzaGJvYXJkIHRvIHZpc3VhbGx5IGludGVycHJldCB0aGUgZGF0YXNldCwgd2l0aCB0aGUgZ29hbCBvZiBleHRyYWN0aW5nIG1lYW5pbmdmdWwgaW5zaWdodHMuIFRoZSBkYXNoYm9hcmQgcHJvbWluZW50bHkgcmV2ZWFscyB0aGF0IHRoZSBvcmdhbml6YXRpb24ncyBmb29kIGRpc3RyaWJ1dGlvbiBpcyBwcmltYXJpbHkgY2VudGVyZWQgaW4gSG91c3RvbiBhbmQgdmFyaW91cyBwYXJ0cyBvZiBUZXhhcy4KCkJ5IHNlZ21lbnRpbmcgdGhlIGRhdGEgYmFzZWQgb24gcGV0IHR5cGVzIGFuZCB6aXAgY29kZXMsIHRoZSBkYXNoYm9hcmQgb2ZmZXJzIGEgc3BlY2lmaWMgb3ZlcnZpZXcsIGhpZ2hsaWdodGluZyB3aGljaCB6aXAgY29kZXMgaGF2ZSBleHBlcmllbmNlZCB0aGUgaGlnaGVzdCBzZXJ2aWNlIGZvciBwZXRzIGFuZCB0aGUgY29ycmVzcG9uZGluZyB0eXBlcyBvZiBwZXRzIHByZXZhbGVudCBpbiB0aG9zZSBhcmVhcy4gVGhlIGFuYWx5c2lzIG9mIGRpc3RyaWJ1dGlvbiBieSBwZXQgdHlwZXMgaW4gY2l0aWVzIHByb3ZpZGVzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIG1ham9yIGNpdGllcyB0aGUgb3JnYW5pemF0aW9uIHNlcnZlcywgYXNzaXN0aW5nIGRlY2lzaW9uLW1ha2VycyBpbiBmb2N1c2luZyBvbiBzcGVjaWZpYyBhcmVhcy4KClRoZSBkaXN0cmlidXRpb24gb2Ygd2V0IGFuZCBkcnkgZm9vZHMgb3ZlciB0aGUgeWVhcnMgcHJvdmlkZXMgYSB0ZW1wb3JhbCB1bmRlcnN0YW5kaW5nIG9mIGhvdyBmb29kIGRpc3RyaWJ1dGlvbiBoYXMgZXZvbHZlZC4gUGFydGljdWxhcmx5IG5vdGV3b3J0aHkgaXMgdGhlIHNpZ25pZmljYW50IGluY3JlYXNlIGluIGZvb2QgZGlzdHJpYnV0aW9uIGR1cmluZyB0aGUgcGFuZGVtaWMgaW4gMjAyMCwgcmVmbGVjdGluZyB0aGUgb3JnYW5pemF0aW9uJ3MgaGVpZ2h0ZW5lZCBlZmZvcnRzIGR1cmluZyBjaGFsbGVuZ2luZyB0aW1lcy4gVGhpcyBkYXRhIGNhbiBwbGF5IGEgY3J1Y2lhbCByb2xlIGluIHBsYW5uaW5nIGNhbXBpbmcgYW5kIGZ1bmRyYWlzaW5nIGFjdGl2aXRpZXMuCgpFeGFtaW5pbmcgZm9vZCBkaXN0cmlidXRpb24gb24gYSBtb250aGx5IGJhc2lzIGZ1cnRoZXIgdW52ZWlscyB0cmVuZHMgaW4gZm9vZCBkZW1hbmQuIFRoZSBkYXNoYm9hcmQgaWxsdXN0cmF0ZXMgYSBwZWFrIGluIGRlbWFuZCBkdXJpbmcgSnVseSwgbWlkLXllYXIsIGFuZCBhbm90aGVyIHN1cmdlIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgeWVhciBpbiBEZWNlbWJlci9KYW51YXJ5LiBUaGlzIGluZm9ybWF0aW9uIGlzIGVzc2VudGlhbCBmb3IgYWRhcHRpbmcgc3RyYXRlZ2llcyB0byBtZWV0IHZhcnlpbmcgZGVtYW5kIHRocm91Z2hvdXQgdGhlIHllYXIuCgojIyBEYXRhIFByZXBhcmF0aW9uIGFuZCBJc3N1ZQoKQ2VydGFpbiBjaGFsbGVuZ2VzIHdlcmUgZW5jb3VudGVyZWQgZHVyaW5nIHRoZSBkYXRhIHByZXBhcmF0aW9uIHBoYXNlIGZvciBkYXRhIGFuYWx5c2lzLiBUaGUgZGF0YXNldCBvcmlnaW5hdGVkIGluIDIwMDEsIGJ1dCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCB0aGUgZGF0YSBjb2xsZWN0aW9uIHByb2Nlc3Mgd2FzIG5vdCBhcyByaWdvcm91cyBpbiB0aGUgZWFybGllciB5ZWFycywgcmVzdWx0aW5nIGluIGEgcmVsYXRpdmVseSBzbWFsbGVyIGRhdGFzZXQgdW50aWwgMjAxMC4gTm90YWJseSwgdGhlcmUgd2VyZSBnYXBzIGluIHRoZSBkYXRhLCBwYXJ0aWN1bGFybHkgaW4gdGhlIHllYXIgMjAwMiB0byAyMDA1LCAyMDA3IHRvIDIwMDkuIENvbnNlcXVlbnRseSwgd2UgbWFkZSB0aGUgZGVjaXNpb24gdG8gZm9jdXMgb3VyIGFuYWx5c2lzIG9uIHRoZSBkYXRhIHN0YXJ0aW5nIGZyb20gMjAxMCwgZW5zdXJpbmcgYSBtb3JlIGNvbXByZWhlbnNpdmUgYW5kIHJlbGlhYmxlIGRhdGFzZXQgZm9yIG91ciBzdHVkeS4KClRvIGFkZHJlc3MgdGhpcywgd2UgbWV0aWN1bG91c2x5IHNlcGFyYXRlZCB0aGUgZGF0YXNldCBpbnRvIHNlZ21lbnRzLCBhbGxvY2F0aW5nIHNwZWNpZmljIHBvcnRpb25zIGZvciB0cmFpbmluZyBhbmQgdGVzdGluZyBwdXJwb3Nlcy4gVGhpcyBzdHJhdGVnaWMgZGl2aXNpb24gYWxsb3dlZCB1cyB0byB3b3JrIHdpdGggYSBtb3JlIGZvY3VzZWQgYW5kIHJvYnVzdCBkYXRhc2V0LCBlbnN1cmluZyB0aGUgYWNjdXJhY3kgYW5kIHJlbGlhYmlsaXR5IG9mIG91ciBhbmFseXNpcy4gQnkgY29uY2VudHJhdGluZyBvbiB0aGUgeWVhcnMgd2l0aCBtb3JlIGNvbnNpc3RlbnQgYW5kIHJlbGlhYmxlIGRhdGEgY29sbGVjdGlvbiBwcmFjdGljZXMsIHdlIGFpbWVkIHRvIGVuaGFuY2UgdGhlIHF1YWxpdHkgYW5kIHZhbGlkaXR5IG9mIG91ciBmaW5kaW5ncy4KYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KCnBldF9kYXRhID0gcmVhZF94bHN4ICgiRnJpZW5kczRMaWZlLnhsc3giKQoKIyBDb252ZXJ0IERhdGUgY29sdW1uIHRvIHByb3BlciBEYXRlIGZvcm1hdApwZXRfZGF0YSREYXRlID0gYXMuRGF0ZShwZXRfZGF0YSREYXRlLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQojaGVhZChwZXRfZGF0YSREYXRlKQojdGFpbChwZXRfZGF0YSREYXRlKQoKI2NvbG5hbWVzKHBldF9kYXRhKQojc3RyKHBldF9kYXRhKQoKIyBPcmRlciBEYXRlCnBldF9kYXRhPC0gcGV0X2RhdGFbb3JkZXIocGV0X2RhdGEkRGF0ZSkgLCBdCiNoZWFkKHBldF9kYXRhKQoKIyBFeHBsb3JlIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEKI3N0cihwZXRfZGF0YSkKCiMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBudW1lcmljIGNvbHVtbnMKI3N1bW1hcnkocGV0X2RhdGEpCgojIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcwojY29sU3Vtcyhpcy5uYShwZXRfZGF0YSkpCgoKYGBgClxuZXdwYWdlCgojIEZvcmVjYXN0aW5nCgpJbiB0aGlzIHByb2plY3QsIG15IHByaW1hcnkgb2JqZWN0aXZlIGlzIHRvIGRldmVsb3AgYWNjdXJhdGUgZm9yZWNhc3RzIGZvciB0aGUgbW9udGhseSBkZW1hbmQgb2YgRHJ5IEZvb2RzIGFuZCBXZXQgRm9vZHMgdXNpbmcgdGltZSBzZXJpZXMgYW5hbHlzaXMgdGVjaG5pcXVlcy4gVG8gYWNoaWV2ZSB0aGlzLCBJIHdpbGwgZW1wbG95IHRoZSAqKkJveC1KZW5raW5zIE1ldGhvZG9sb2d5KiosIGEgd2lkZWx5IHJlc3BlY3RlZCBhcHByb2FjaCBmb3IgdGltZSBzZXJpZXMgZm9yZWNhc3RpbmcgQGVud2lraToxMDk3MzMyMDgwLgoKVGhlIGZpcnN0IHN0ZXAgaW52b2x2ZXMgYSB0aG9yb3VnaCBleGFtaW5hdGlvbiBvZiB0aGUgJ0ZyaWVuZHMgZm9yIExpZmUnIGRhdGFzZXQsIGV4cGxvcmluZyBpdHMgaGlzdG9yaWNhbCByZWNvcmRzIHRvIHVuZGVyc3RhbmQgdGhlIGJlaGF2aW9yIG9mIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRlbWFuZHMgb3ZlciB0aW1lLiBBQ0YgYW5kIFBBQ0YgcGxvdHMgd2lsbCBiZSBnZW5lcmF0ZWQgdG8gdW5jb3ZlciBhdXRvY29ycmVsYXRpb24gcGF0dGVybnMgd2l0aGluIHRoZSBkYXRhLCBjcnVjaWFsIGZvciBpZGVudGlmeWluZyBwb3RlbnRpYWwgc2Vhc29uYWxpdHkgYW5kIHRyZW5kIGNvbXBvbmVudHMuIEluIGNhc2UgdGhlIGRhdGFzZXQgbGFja3Mgc2Vhc29uYWxpdHksIEkgd2lsbCBpbXBsZW1lbnQgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIHN0YWJpbGl6ZSB0aGUgZGF0YSBmb3IgYWNjdXJhdGUgZm9yZWNhc3RpbmcuCgpUaGUgZGF0YXNldCB3aWxsIGJlIHNwbGl0IGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cyB0byBmYWNpbGl0YXRlIHByZWNpc2UgbW9kZWwgZXZhbHVhdGlvbi4gRXNzZW50aWFsIHByZXByb2Nlc3Npbmcgc3RlcHMsIGluY2x1ZGluZyBoYW5kbGluZyBtaXNzaW5nIHZhbHVlcyBhbmQgb3V0bGllcnMsIHdpbGwgYmUgZXhlY3V0ZWQgdG8gZW5zdXJlIGRhdGEgaW50ZWdyaXR5LgoKSSB3aWxsIGxldmVyYWdlIHRoZSAqKmF1dG8tYXJpbWEqKiAoQXV0by1BdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlICkgYWxnb3JpdGhtIHRvIGF1dG9tYXRpY2FsbHkgc3VnZ2VzdCBzdWl0YWJsZSBtb2RlbHMgYmFzZWQgb24gdGhlIGRhdGFzZXQncyBjaGFyYWN0ZXJpc3RpY3MuIFRoZSByZXNpZHVhbHMgd2lsbCBiZSBhbmFseXplZCB1c2luZyAqKlNBUklNQSoqIChTZWFzb25hbCBBdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlKSBtb2RlbHMgdG8gY29uZmlybSB0aGUgYWJzZW5jZSBvZiBzeXN0ZW1hdGljIHBhdHRlcm5zLCBlbnN1cmluZyB0aGUgZm9yZWNhc3QncyByZWxpYWJpbGl0eS4gT25jZSB0aGUgbW9kZWxzIGFyZSBzZWxlY3RlZCBhbmQgdHJhaW5lZCBvbiB0aGUgdHJhaW5pbmcgZGF0YSwgd2Ugd2lsbCBwcm9jZWVkIHRvIGdlbmVyYXRlIG1vbnRobHkgZm9yZWNhc3RzIGZvciBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkZW1hbmQuIFByZWRpY3Rpb25zIHdpbGwgYmUgY29tcGFyZWQgYWdhaW5zdCB0aGUgYWN0dWFsIHRlc3QgZGF0YSB0byBhc3Nlc3MgdGhlIG1vZGVsJ3MgYWNjdXJhY3kgYW5kIHJlbGlhYmlsaXR5LiBQZXJmb3JtYW5jZSBtZXRyaWNzIHN1Y2ggYXMgTWVhbiBBYnNvbHV0ZSBFcnJvciAoTUFFKSwgUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3IgKFJNU0UpLCBhbmQgTUFQRSAoTWVhbiBBYnNvbHV0ZSBQZXJjZW50YWdlIEVycm9yKSB3aWxsIGJlIGNvbXB1dGVkIHRvIHF1YW50aWZ5IHRoZSBmb3JlY2FzdGluZyBhY2N1cmFjeS4KCgojIFN0YXRpc3RpY2FsIE1ldGhvZG9sb2d5CgojIyBUaW1lIFNlcmlzZXMgQW5hbHlzaXMKClRpbWUgc2VyaWVzIGFuYWx5c2lzIGlzIGEgc3RhdGlzdGljYWwgdGVjaG5pcXVlIHVzZWQgdG8gYW5hbHl6ZSBhbmQgZm9yZWNhc3QgZGF0YSBwb2ludHMgY29sbGVjdGVkIG9yIHJlY29yZGVkIGF0IHJlZ3VsYXIgdGltZSBpbnRlcnZhbHMuIEluIHRoZSBjb250ZXh0IG9mIHRoaXMgcHJvamVjdCwgd2hpY2ggaW52b2x2ZXMgZm9yZWNhc3RpbmcgbW9udGhseSBkZW1hbmQgZm9yIERyeSBGb29kIGFuZCBXZXQgRm9vZCBwcm9kdWN0cywgdGltZSBzZXJpZXMgYW5hbHlzaXMgd2lsbCBoZWxwIHRvIHVuY292ZXIgcGF0dGVybnMsIHRyZW5kcywgYW5kIHNlYXNvbmFsaXR5IHdpdGhpbiB0aGUgaGlzdG9yaWNhbCBkYXRhLiBHYXRoZXIgaGlzdG9yaWNhbCBkYXRhIG9uIG1vbnRobHkgRHJ5IEZvb2QgYW5kIFdldCBGb29kIGRlbWFuZC4gRWFjaCBkYXRhIHBvaW50IHJlcHJlc2VudHMgdGhlIGRlbWFuZCBmb3IgYSBzcGVjaWZpYyBtb250aCBbQGNoYXRmaWVsZDIwMDB0aW1lXS4KCiQkIHlfdCA9IFRfdCArIFNfdCArIGVfdCBcXAokJAokJApcdGV4dHtXaGVyZTp9XFwKXGJlZ2lue2FsaWduKn0KICAgIHlfdCAmIDogXHRleHR7VGltZSBzZXJpZXMgZnVuY3Rpb259IFxcCiAgICBUX3QgJiA6IFx0ZXh0e1RyZW5kfSBcXAogICAgU190ICYgOiBcdGV4dHtTZWFzb25hbGl0eX0gXFwKICAgIGVfdCAmIDogXHRleHR7UmVzaWR1YWx9ClxlbmR7YWxpZ24qfSAkJAoKCgpgYGB7cixmaWcud2lkdGg9Ni41LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBEcnkgRm9vZHMgZnJvbSB5ZWFyIG9mIDIwMDEKZHJ5Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJEcnkgRm9vZHMiLCBzdGFydCA9IGMoMjAwMSwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBXZXQgRm9vZHMKd2V0Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJXZXQgRm9vZHMiLCBzdGFydCA9IGMoMjAwMSwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiNhdXRvcGxvdCh3ZXRmb29kX2RhdGEpCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgcGxvdCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBmb29kcyBDb25zdW1wdGlvbgpwYXIobWZyb3c9YygzLDEpKQpwbG90LnRzKGRyeWZvb2RfZGF0YSwgbWFpbiA9ICJEcnkgRm9vZHMgQ29tc3VtcHRpb24gT3ZlciBUaW1lIixjZXgubWFpbj0xLjUsIGNleC5sYWI9MywgY2V4LmF4aXM9MykKcGxvdC50cyh3ZXRmb29kX2RhdGEsIG1haW4gPSAiV2V0IEZvb2RzIENvbXN1bXB0aW9uIE92ZXIgVGltZSIsY2V4Lm1haW49MS41LCBjZXgubGFiPTMsIGNleC5heGlzPTMpCmBgYApUaGUgcGxvdCBleGhpYml0ZWQgYW4gaW5jcmVhc2UgaW4gdmFyaWFiaWxpdHkgb3ZlciB0aW1lLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGRpc3BlcnNpb24gb2YgdGhlIGRhdGEgcG9pbnRzIHdhcyBub3QgY29uc3RhbnQuIFN1Y2ggY2hhcmFjdGVyaXN0aWNzIGluIHRoZSBkYXRhIGNhbiBwb3NlIGNoYWxsZW5nZXMgZm9yIGFjY3VyYXRlIG1vZGVsaW5nIGFuZCBmb3JlY2FzdGluZy4KClxuZXdwYWdlCgpgYGB7ciwgZmlnLndpZHRoPTYuNSxmaWcuaGVpZ2h0PTgsZWNobz1GQUxTRX0KCgojTG9nLVRyYW5zZm9ybWVkIERyeSBGb29kcwpkcnlmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJEcnkgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMDEsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIExvZy1UcmFuc2Zvcm1lZCBXZXQgRm9vZAp3ZXRmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJXZXQgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMDEsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgoKcGFyKG1mcm93PWMoMywxKSkKCnBsb3QoZHJ5Zm9vZF9kYXRhLCBtYWluID0gIkxvZy1UcmFuc2Zvcm1lZCBEcnkgRm9vZHMgQ29uc3VtcHRpb24gT3ZlciBUaW1lIiwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJMb2coRHJ5IEZvb2RzKSIpCgoKcGxvdCh3ZXRmb29kX2RhdGEsIG1haW4gPSAiTG9nLVRyYW5zZm9ybWVkIFdldCBGb29kcyBDb25zdW1wdGlvbiBPdmVyIFRpbWUiLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIkxvZyhXZXQgRm9vZHMpIikKCgpgYGAKIyMgTG9nLVRyYW5zZm9ybWVkIERhdGEgCgpMb2cgdHJhbnNmb3JtYXRpb24gaXMgdXNlZCBpbiB0aW1lIHNlcmllcyBhbmFseXNpcyB0byBzdGFiaWxpemUgdGhlIHZhcmlhbmNlIGFuZCBwcm9tb3RlIHN0YXRpb25hcml0eS4gU3RhdGlvbmFyaXR5IGlzIGEgZGVzaXJhYmxlIHByb3BlcnR5IGluIHRpbWUgc2VyaWVzIGRhdGEsIHdoZXJlIHN0YXRpc3RpY2FsIHByb3BlcnRpZXMgc3VjaCBhcyBtZWFuIGFuZCB2YXJpYW5jZSByZW1haW4gY29uc3RhbnQgb3ZlciB0aW1lLiBMb2cgdHJhbnNmb3JtYXRpb24gaGVscHMgYWNoaWV2ZSB0aGlzIGJ5IGFkZHJlc3NpbmcgaXNzdWVzIGxpa2UgaGV0ZXJvc2NlZGFzdGljaXR5LCB3aGljaCBpcyB0aGUgcHJlc2VuY2Ugb2YgY2hhbmdpbmcgdmFyaWFuY2UgaW4gdGhlIGRhdGEuCgpUaGUgbG9nIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBkYXRhIGlzIGEgY3J1Y2lhbCBzdGVwIGluIGVuaGFuY2luZyBpdHMgc3RhYmlsaXR5LCBpbnRlcnByZXRhYmlsaXR5LCBhbmQgc3VpdGFiaWxpdHkgZm9yIGZ1cnRoZXIgdGltZSBzZXJpZXMgYW5hbHlzaXMgYW5kIGZvcmVjYXN0aW5nIGluIHRoaXMgcHJvamVjdC4gQWZ0ZXIgaW1wbGVtZW50aW5nIHRoZSAqKmxvZ2FyaXRobWljIHRyYW5zZm9ybWF0aW9uKiosIHRoZSByZXN1bHRpbmcgcGxvdCBkaXNwbGF5ZWQgYSBtb3JlIHN0YWJpbGl6ZWQgYW5kIHBvdGVudGlhbGx5IHN0YXRpb25hcnkgcGF0dGVybi4gVGhlIGRhdGEgZXhoaWJpdGVkIHJlZHVjZWQgdmFyaWFuY2UsIGFuZCBhIGNvbnNpc3RlbnQgbWVhbiBwYXR0ZXJuIGVtZXJnZWQsIHN1Z2dlc3RpbmcgYSBzdGF0aW9uYXJ5IGJlaGF2aW9yLiBUaGlzIHN0YWJpbGl6ZWQgZGF0YXNldCBmb3JtcyBhIG1vcmUgcmVsaWFibGUgZm91bmRhdGlvbiBmb3Igc3Vic2VxdWVudCB0aW1lIHNlcmllcyBhbmFseXNpcy4KClRoZSBsb2cgdHJhbnNmb3JtYXRpb24gbm90IG9ubHkgYWRkcmVzc2VzIGNvbmNlcm5zIHJlbGF0ZWQgdG8gdmFyaWFuY2UgaW5zdGFiaWxpdHkgYnV0IGFsc28gaW1wcm92ZXMgdGhlIGludGVycHJldGFiaWxpdHkgb2YgdGhlIGRhdGEgQGJvZWhtMjAxNHByb21vdGluZy4gQnkgcHJvbW90aW5nIHN0YXRpb25hcml0eSwgdGhpcyB0cmFuc2Zvcm1hdGlvbiBsYXlzIHRoZSBncm91bmR3b3JrIGZvciBjb25kdWN0aW5nIHJvYnVzdCBhbmQgYWNjdXJhdGUgdGltZSBzZXJpZXMgYW5hbHlzaXMuIENvbnNlcXVlbnRseSwgaXQgZmFjaWxpdGF0ZXMgZWZmZWN0aXZlIGZvcmVjYXN0aW5nIGluIHRoZSBsYXRlciBzdGFnZXMgb2YgdGhlIHByb2plY3QuCgojIyBEYXRhIFByZXBhcmF0aW9uIGFuZCBJc3N1ZQoKQ2VydGFpbiBjaGFsbGVuZ2VzIHdlcmUgZW5jb3VudGVyZWQgZHVyaW5nIHRoZSBkYXRhIHByZXBhcmF0aW9uIHBoYXNlIGZvciBkYXRhIGFuYWx5c2lzLiBUaGUgZGF0YXNldCBvcmlnaW5hdGVkIGluIDIwMDEsIGJ1dCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCB0aGUgZGF0YSBjb2xsZWN0aW9uIHByb2Nlc3Mgd2FzIG5vdCBhcyByaWdvcm91cyBpbiB0aGUgZWFybGllciB5ZWFycywgcmVzdWx0aW5nIGluIGEgcmVsYXRpdmVseSBzbWFsbGVyIGRhdGFzZXQgdW50aWwgMjAxMC4gTm90YWJseSwgdGhlcmUgd2VyZSBnYXBzIGluIHRoZSBkYXRhLCBwYXJ0aWN1bGFybHkgaW4gdGhlIHllYXIgMjAwMiB0byAyMDA1LCAyMDA3IHRvIDIwMDkuIENvbnNlcXVlbnRseSwgSSBtYWRlIHRoZSBkZWNpc2lvbiB0byBmb2N1cyB0aGlzIGFuYWx5c2lzIG9uIHRoZSBkYXRhIHN0YXJ0aW5nIGZyb20gMjAxMCwgZW5zdXJpbmcgYSBtb3JlIGNvbXByZWhlbnNpdmUgYW5kIHJlbGlhYmxlIGRhdGFzZXQgZm9yIHRoaXMgc3R1ZHkuCgpUbyBhZGRyZXNzIHRoaXMsIHdlIG1ldGljdWxvdXNseSBzZXBhcmF0ZWQgdGhlIGRhdGFzZXQgaW50byBzZWdtZW50cywgYWxsb2NhdGluZyBzcGVjaWZpYyBwb3J0aW9ucyBmb3IgdHJhaW5pbmcgYW5kIHRlc3RpbmcgcHVycG9zZXMuIFRoaXMgc3RyYXRlZ2ljIGRpdmlzaW9uIGFsbG93ZWQgdXMgdG8gd29yayB3aXRoIGEgbW9yZSBmb2N1c2VkIGFuZCByb2J1c3QgZGF0YXNldCwgZW5zdXJpbmcgdGhlIGFjY3VyYWN5IGFuZCByZWxpYWJpbGl0eSBvZiBvdXIgYW5hbHlzaXMuIEJ5IGNvbmNlbnRyYXRpbmcgb24gdGhlIHllYXJzIHdpdGggbW9yZSBjb25zaXN0ZW50IGFuZCByZWxpYWJsZSBkYXRhIGNvbGxlY3Rpb24gcHJhY3RpY2VzLCB3ZSBhaW1lZCB0byBlbmhhbmNlIHRoZSBxdWFsaXR5IGFuZCB2YWxpZGl0eSBvZiBvdXIgZmluZGluZ3MuCgojIyMgU3BsaXRpbmcgRGF0YQoKRm9yIHRoZSBEcnkgRm9vZCBkYXRhc2V0LCA5NSUgb2YgdGhlIGRhdGEgd2FzIGFsbG9jYXRlZCBmb3IgdHJhaW5pbmcsIHdoaWxlIDUlIHdhcyByZXNlcnZlZCBmb3IgdGVzdGluZywgZW5zdXJpbmcgYSB0aG9yb3VnaCBhbmQgcm9idXN0IGV2YWx1YXRpb24uIFNpbWlsYXJseSwgdGhlIFdldCBGb29kIGRhdGFzZXQgZW1wbG95ZWQgYSBzcGxpdCBvZiA5OCUgZm9yIHRyYWluaW5nIGFuZCAyJSBmb3IgdGVzdGluZywgY29udHJpYnV0aW5nIHRvIHRoZSBlbmhhbmNlbWVudCBvZiB0aGUgbW9kZWwncyBwcmVkaWN0aXZlIGFjY3VyYWN5LgoKYGBge3IsZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJ30KIyBEcnkgRm9vZHMKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKI2RyeWZvb2RfZGF0YSA9IGxvZyhkcnlmb29kX2RhdGEpCmRyeWZvb2RfZGF0YSA8LSB0cyhsb2cocGV0X2RhdGEkIkRyeSBGb29kcyIpLCBzdGFydCA9IGMoMjAxMCwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgOTUlIGZvciB0cmFpbmluZywgNSUgZm9yIHRlc3RpbmcpCnNwbGl0X3BvaW50IDwtIGZsb29yKDAuOTUgKiBsZW5ndGgoZHJ5Zm9vZF9kYXRhKSkKCiMgU3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzCmRyeWZvb2QgPC0gd2luZG93KGRyeWZvb2RfZGF0YSwgc3RhcnQgPSBzdGFydChkcnlmb29kX2RhdGEpLCBlbmQgPSB0aW1lKGRyeWZvb2RfZGF0YSlbc3BsaXRfcG9pbnRdKQoKIyBDcmVhdGUgdGhlIHRlc3RpbmcgZGF0YQpkcnlmb29kX3Rlc3QgPC0gd2luZG93KGRyeWZvb2RfZGF0YSwgc3RhcnQgPSB0aW1lKGRyeWZvb2RfZGF0YSlbc3BsaXRfcG9pbnQgKyAxXSkKCiMgQ2hlY2sgdGhlIGxlbmd0aHMgb2YgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YQpsZW5ndGgoZHJ5Zm9vZCkKbGVuZ3RoKGRyeWZvb2RfdGVzdCkKaGVhZChkcnlmb29kX3Rlc3QpCnRhaWwoZHJ5Zm9vZF90ZXN0KQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIFdldEZvb2RzIGZyb20gdGhlIHllYXIgMjAxMAp3ZXRmb29kX2RhdGEgPC0gdHMobG9nKHBldF9kYXRhJCJXZXQgRm9vZHMiKSwgc3RhcnQgPSBjKDIwMTAsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIFNldCB0aGUgc3BsaXQgcG9pbnQgKGUuZy4sIDk4JSBmb3IgdHJhaW5pbmcsIDIlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjk4ICogbGVuZ3RoKHdldGZvb2RfZGF0YSkpCgojIFNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cwp3ZXRmb29kIDwtIHdpbmRvdyh3ZXRmb29kX2RhdGEsIHN0YXJ0ID0gc3RhcnQod2V0Zm9vZF9kYXRhKSwgZW5kID0gdGltZSh3ZXRmb29kX2RhdGEpW3NwbGl0X3BvaW50XSkKCiMgQ3JlYXRlIHRoZSB0ZXN0aW5nIGRhdGEKd2V0Zm9vZF90ZXN0IDwtIHdpbmRvdyh3ZXRmb29kX2RhdGEsIHN0YXJ0ID0gdGltZSh3ZXRmb29kX2RhdGEpW3NwbGl0X3BvaW50ICsgMV0pCgojIENoZWNrIHRoZSBsZW5ndGhzIG9mIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEKI2xlbmd0aCh0cmFpbl9kYXRhKQojbGVuZ3RoKHRlc3RfZGF0YSkKCmBgYAoKIyBCb3gtSmVua2lucyBNZXRob2QKCkluIHRoZSBmb2xsb3dpbmcgcGFnZXMgSSB3aWxsIGZvbGxvdyB0aGUgQm94LUplbmtpbnMgTWV0aG9kIHRvIGlkZW50aWZ5IGFuZCBldmFsdWF0ZSBtb2RlbHMgZm9yIGZvcmVjYXN0aW5nLiBUaGUgKipCb3gtSmVua2lucyBNZXRob2QqKiwgYWxzbyBrbm93biBhcyB0aGUgQm94LUplbmtpbnMgYXBwcm9hY2ggb3IgQm94LUplbmtpbnMgbWV0aG9kb2xvZ3ksIGlzIGEgc3lzdGVtYXRpYyBhbmQgd2lkZWx5IHVzZWQgdGVjaG5pcXVlIGZvciB0aW1lIHNlcmllcyBhbmFseXNpcyBhbmQgZm9yZWNhc3RpbmcuIERldmVsb3BlZCBieSBHZW9yZ2UgQm94IGFuZCBHd2lseW0gSmVua2lucyBpbiB0aGUgZWFybHkgMTk3MHMsIHRoaXMgbWV0aG9kIGlzIHBhcnRpY3VsYXJseSBlZmZlY3RpdmUgZm9yIG1vZGVsaW5nIGFuZCBwcmVkaWN0aW5nIHVuaXZhcmlhdGUgdGltZSBzZXJpZXMgZGF0YS4gVGhlIGtleSBjb21wb25lbnRzIG9mIHRoZSBCb3gtSmVua2lucyBNZXRob2QgaW5jbHVkZTogCgoqIE1vZGVsIGlkZW50aWZpY2F0aW9uCiogTW9kZWwgZXN0aW1hdGlvbiBhbmQgCiogRGlhZ25vc3RpYyBjaGVja2luZwoKVG8gaW5pdGlhdGUgdGhpcyBwcm9jZXNzIGZvciBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRhdGEsIEkgd2lsbCBiZWdpbiBieSBvYnNlcnZpbmcgdGhlIEFDRiBhbmQgUEFDRi4gVGhpcyBpbml0aWFsIGV4cGxvcmF0aW9uIGFpbXMgdG8gdW5kZXJzdGFuZCB0aGUgZGF0YSdzIGJlaGF2aW9yIGFuZCBhc3Nlc3MgaXRzIHN1aXRhYmlsaXR5IGZvciBtb2RlbGluZy4gQWZ0ZXIgdGhhdCBJIHdpbGwgcHJvY2VlZCB0byBlc3RpbWF0ZSBhbiBBUklNQSBtb2RlbCB1c2luZyB0aGUgYXV0by1hcmltYSBmdW5jdGlvbiwgd2hpY2ggc3VnZ2VzdHMgYW4gYXBwcm9wcmlhdGUgbW9kZWwgYmFzZWQgb24gdGhlIG9ic2VydmVkIEFDRiBhbmQgUEFDRi4gRm9sbG93aW5nIG1vZGVsIGVzdGltYXRpb24sIHRob3JvdWdoIGNoZWNrcyBvbiB0aGUgcmVzaWR1YWxzIHdpbGwgYmUgY29uZHVjdGVkIHRvIGVuc3VyZSB0aGUgbW9kZWwncyBhZGVxdWFjeS4KCiMgTW9kZWwgSWRlbnRpZmljYXRpb24KCiMjIEFuYWx5emluZyBBQ0YgYW5kIFBBQ0YKCkFDRiBhbmQgUEFDIGFyZSBlc3NlbnRpYWwgdG9vbHMgaW4gdGltZSBzZXJpZXMgYW5hbHlzaXMsIGVzcGVjaWFsbHkgd2hlbiBkZWFsaW5nIHdpdGggc3RhdGlvbmFyeSBkYXRhIGxpa2Ugb3VyIERyeSBGb29kIGFuZCBXZXQgRm9vZCBkYXRhc2V0LgoKQXV0b0NvcnJlbGF0aW9uIEZ1bmN0aW9uIChBQ0YpOgpBQ0YgbWVhc3VyZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYSB0aW1lIHNlcmllcyBhbmQgaXRzIGxhZ2dlZCB2YWx1ZXMuSW4gYSBzdGF0aW9uYXJ5IHNlcmllcywgQUNGIGhlbHBzIGlkZW50aWZ5IHBhdHRlcm5zIGFuZCBkZXBlbmRlbmNpZXMgaW4gdGhlIGRhdGEgb3ZlciBkaWZmZXJlbnQgdGltZSBsYWdzLiBUeXBpY2FsbHksIGhvcml6b250YWwgbGluZXMgYXJlIGRyYXduIG9uIHRoZSBBQ0YgcGxvdCB0byBpbmRpY2F0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIFBvaW50cyBvdXRzaWRlIHRoZXNlIGxpbmVzIHN1Z2dlc3Qgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9uLgpFcXVhdGlvbjoKCiQkIEFDRihoKSA9IFxmcmFje1xzdW1fe3Q9MX1ee1QtaH0oeV90IC0gXGJhcnt5fSkoeV97dCtofSAtIFxiYXJ7eX0pfXtcc3VtX3t0PTF9XntUfSh5X3QgLSBcYmFye3l9KV4yfSBcXApcdGV4dHtXaGVyZTp9ClxcICB5X3RcIGlzXCB0aGVcIHZhbHVlXCBvZlwgdGhlXCB0aW1lXCBzZXJpZXNcIGF0XCB0aW1lXCB0LgpcXCBcYmFye3l9XCBpc1wgdGhlXCBtZWFuXCBvZlwgdGhlXCAgdGltZVwgc2VyaWVzLgpcXCBUXCAgaXNcICB0aGVcICB0b3RhbFwgIG51bWJlclwgIG9mIFwgb2JzZXJ2YXRpb25zXCAgaW5cIHRoZVwgIHRpbWVcICBzZXJpZXMuIFxcICQkCgpQYXJ0aWFsIEF1dG9Db3JyZWxhdGlvbiBGdW5jdGlvbiAoUEFDRik6ClBBQ0YgbWVhc3VyZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYSB0aW1lIHNlcmllcyBhbmQgaXRzIGxhZ2dlZCB2YWx1ZXMsIHJlbW92aW5nIHRoZSBlZmZlY3Qgb2YgaW50ZXJtZWRpYXRlIGxhZ3MuUEFDRiBpcyB1c2VmdWwgZm9yIGlkZW50aWZ5aW5nIHRoZSBkaXJlY3QgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIG9ic2VydmF0aW9ucyBhdCBkaWZmZXJlbnQgdGltZSBwb2ludHMsIGV4Y2x1ZGluZyB0aGUgaW5mbHVlbmNlIG9mIG90aGVyIGxhZ3MuU2ltaWxhciB0byBBQ0YsIGhvcml6b250YWwgbGluZXMgYXJlIHVzZWQgYXMgcmVmZXJlbmNlIGZvciBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuCkVxdWF0aW9uOgoKJCQgUEFDRihoKSA9IFxmcmFje1x0ZXh0e2Nvdn0oeV90LCB5X3t0LWh9fFx7eV97dC0xfSwgeV97dC0yfSwgXGxkb3RzLCB5X3t0LWgrMX1cfSl9e1xzcXJ0e1x0ZXh0e3Zhcn0oeV90KVx0ZXh0e3Zhcn0oeV97dC1ofXxce3lfe3QtMX0sIHlfe3QtMn0sIFxsZG90cywgeV97dC1oKzF9XH0pfX0gXFwKJCQKJCRcdGV4dHtXaGVyZTp9ClxcIGNvdih5X3QsIHlfe3QtaH18XHt5X3t0LTF9LCB5X3t0LTJ9LCBcbGRvdHMsIHlfe3QtaCsxfVx9KSBpc1wgdGhlXCBjb25kaXRpb25hbFwgY292YXJpYW5jZVwgYmV0d2VlblwgeV90XCBhbmRcIHlfe3QtaH1cIGdpdmVuXCAgdGhlXCAgdmFsdWVzXCAgYXRcICBpbnRlcm1lZGlhdGVcICBsYWdzClxcIHZhcih5X3QpIGlzXCB0aGVcIHVuY29uZGl0aW9uYWxcIHZhcmlhbmNlXCBvZlwgeV90CiBcXCB7dmFyfSh5X3t0LWh9fFx7eV97dC0xfSwgeV97dC0yfSwgXGxkb3RzLCB5X3t0LWgrMX1cfVwgaXNcIHRoZVwgY29uZGl0aW9uYWxcIHZhcmlhbmNlXCBvZlwgeV97dC1ofVwgZ2l2ZW5cIHRoZVwgdmFsdWVzXCBhdFwgaW50ZXJtZWRpYXRlXCBsYWdzLiBcXCAkJAogCgpgYGB7ciwgZmlnLndpZHRoPTcsZmlnLmhlaWdodD0zLGVjaG89RkFMU0V9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkoZ2dwbG90MikKIyMjIyBEcnkgRm9vZHMgIyMjIyMKIyBQbG90IEFDRiBhbmQgUEFDRiBzaWRlIGJ5IHNpZGUKcGFyKG1mcm93PWMoMSwyKSkKCiMgUGxvdCBBQ0YgZm9yIERyeSBGb29kcwphY2YoZHJ5Zm9vZCxsYWcubWF4ID0gMTIsICBtYWluID0gIkFDRiBmb3IgRHJ5IEZvb2RzIikKCiMgUGxvdCBQQUNGIGZvciBEcnkgRm9vZHMKcGFjZihkcnlmb29kLCBwYWNmID0gVFJVRSwgbGFnLm1heCA9IDEyLCBtYWluID0gIlBBQ0YgZm9yIERyeSBGb29kcyIpCgpgYGAKQUNGIGFuZCBQQUNGIHBsb3RzIGZvciBEcnkgRm9vZHMgZGF0YSBpcyB3aXRoaW4gdGhlIGd1aWRlZCBsaW5lcyB3aGljaCBtZWFuIGRhdGEgaXMgc3RhdGlvbmFyeSBhbmQgaXQgaXMgYSBwb3NpdGl2ZSBzaWduLiBJdCBpbXBsaWVzIHRoYXQgdGhlcmUgYXJlIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbnMgYmV5b25kIHRoZSBmaXJzdCBsYWcsIGluZGljYXRpbmcgdGhhdCB0aGUgaGlzdG9yaWNhbCB2YWx1ZXMgb2YgdGhlIHNlcmllcyBkbyBub3QgY29udHJpYnV0ZSBzaWduaWZpY2FudGx5IHRvIHRoZSBjdXJyZW50IG9ic2VydmF0aW9uLiAKCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9MyxlY2hvPUZBTFNFfQojIyMjIFdldCBGb29kcyAjIyMjIwojIFBsb3QgQUNGIGFuZCBQQUNGIHNpZGUgYnkgc2lkZQpwYXIobWZyb3c9YygxLDIpKQoKIyBQbG90IEFDRiBmb3IgV2V0IEZvb2RzCmFjZih3ZXRmb29kLCBsYWcubWF4ID0gMTIsIG1haW4gPSAiQUNGIGZvciBXZXQgRm9vZHMiKQoKIyBQbG90IFBBQ0YgZm9yIERyeSBGb29kcwpwYWNmKHdldGZvb2QsIGxhZy5tYXggPSAxMiwgbWFpbiA9ICJQQUNGIGZvciBXZXQgRm9vZHMiKQoKYGBgCgpUaGUgQUNGIGFuZCBQQUNGIGZvciBXZXQgRm9vZHMgZGF0YSBjdXQgb2ZmIGFmdGVyIHRoZSBmaXJzdCBsYWcsIGl0IGluZGljYXRlcyB0aGF0IHRoZXJlIGlzIGxpa2VseSBubyBzaWduaWZpY2FudCBhdXRvY29ycmVsYXRpb24gb3IgcGFydGlhbCBhdXRvY29ycmVsYXRpb24gYmV5b25kIHRoZSBmaXJzdCBsYWcuVGhpcyBpbXBsaWVzIHRoYXQgdGhlIHdldCBmb29kIGRhdGEgaXMgc3RhdGlvbmFyeSwgZG8gbm90IGV4aGliaXQgYSBwZXJzaXN0ZW50IHRyZW5kIG9yIHBhdHRlcm4gb3ZlciB0aW1lLiBUaGlzIG9ic2VydmF0aW9uIHByb3ZpZGVzIGNvbmZpZGVuY2UgaW4gdGhlIHN0YWJpbGl0eSBvZiB0aGUgd2V0IGZvb2QgY29uc3VtcHRpb24gcGF0dGVybiBhbmQgYWxsb3dzIHVzIHRvIHByb2NlZWQgd2l0aCBtb2RlbGluZyBlZmZvcnRzLCBmb2N1c2luZyBvbiB0aGUgcHJpbWFyeSBkZXBlbmRlbmNpZXMgY2FwdHVyZWQgYnkgdGhlIGZpcnN0IGxhZy4gClxuZXdwYWdlCgojICBNb2RlbCBFc3RpbWF0aW9uCgojIyBBUklNQSBNb2RlbAoKVGhlIEF1dG9SZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKCpBUklNQSopIGlzIGEgd2lkZWx5IHVzZWQgdGltZSBzZXJpZXMgYW5hbHlzaXMgYW5kIGZvcmVjYXN0aW5nIG1vZGVsLiBJdCBjb21iaW5lcyB0aHJlZSBrZXkgY29tcG9uZW50cyB0byBjYXB0dXJlIGRpZmZlcmVudCBhc3BlY3RzIG9mIHRpbWUgc2VyaWVzIGRhdGE6IEF1dG9SZWdyZXNzaXZlIChBUiksIEludGVncmF0ZWQgKEkpLCBhbmQgTW92aW5nIEF2ZXJhZ2UgKE1BKS4KClRoZSBtb2RlbGluZyBhcHByb2FjaCB3aWxsIGJlIHRvIHVzZSB0aGUgYXV0by5hcmltYSBmdW5jdGlvbiBmcm9tIHRoZSBmb3JlY2FzdCBwYWNrYWdlIHRvIHN1Z2dlc3QgbW9kZWxzIGZvciBlYWNoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIHNjZW5hcmlvLiBBdXRvcmVncmVzc2l2ZSBJbnRlZ3JhdGVkIE1vdmluZyBBdmVyYWdlIE1vZGVsICoqQVJJTUEqKiAgaXMgYSB0aW1lIHNlcmllcyBhbmFseXNpcyBhbmQgZm9yZWNhc3RpbmcgbWV0aG9kLFRoZSBBUklNQSBtb2RlbCBpcyBkZW5vdGVkIGFzIEFSSU1BKHAsIGQsIHEpLCAKd2hlcmU6CnA6IEl0IGlzIHRoZSBvcmRlciBvZiB0aGUgYXV0b3JlZ3Jlc3NpdmUgcGFydCAoQVIpLgpkOiBUaGUgZGVncmVlIG9mIGRpZmZlcmVuY2luZyBuZWVkZWQgdG8gbWFrZSB0aGUgdGltZSBzZXJpZXMgZGF0YSBzdGF0aW9uYXJ5LgpxOiBUaGUgb3JkZXIgb2YgdGhlIG1vdmluZyBhdmVyYWdlIHBhcnQgKE1BKS4KVGhlIEFSSU1BIG1vZGVsIGlzIHBvd2VyZnVsIGZvciBoYW5kbGluZyBhIHdpZGUgcmFuZ2Ugb2YgdGltZSBzZXJpZXMgcGF0dGVybnMsIGluY2x1ZGluZyB0cmVuZCwgc2Vhc29uYWxpdHksIGFuZCBjeWNsaWMgcGF0dGVybnMuIEl0IGlzIHdpZGVseSB1c2VkIGZvciBmb3JlY2FzdGluZyBmdXR1cmUgdmFsdWVzIGJhc2VkIG9uIGhpc3RvcmljYWwgb2JzZXJ2YXRpb25zLgoKCkFSOgpBdXRvUmVncmVzc2l2ZSAoQVIpIHJlcHJlc2VudHMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBjdXJyZW50IG9ic2VydmF0aW9uIGFuZCBpdHMgcHJldmlvdXMgb2JzZXJ2YXRpb25zLCB3aXRoIHRoZSBpZGVhIHRoYXQgcGFzdCB2YWx1ZXMgY2FuIGJlIHVzZWZ1bCBpbiBwcmVkaWN0aW5nIGZ1dHVyZSB2YWx1ZXMuIAoKJCQgeV90ID0gXHBoaV8xIHlfe3QtMX0gKyBccGhpXzIgeV97dC0yfSArIFxsZG90cyArIFxwaGlfcCB5X3t0LXB9ICsgXHZhcmVwc2lsb25fdCBcXCAkJApNQToKTW92aW5nIEF2ZXJhZ2UgKE1BKSByZXByZXNlbnRzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgY3VycmVudCBvYnNlcnZhdGlvbiBhbmQgYSByZXNpZHVhbCBlcnJvciBmcm9tIGEgbW92aW5nIGF2ZXJhZ2UgbW9kZWwgYXBwbGllZCB0byBwYXN0IG9ic2VydmF0aW9ucy4KCiQkIHlfdCA9IFx2YXJlcHNpbG9uX3QgLSBcdGhldGFfMSBcdmFyZXBzaWxvbl97dC0xfSAtIFx0aGV0YV8yIFx2YXJlcHNpbG9uX3t0LTJ9IC0gXGxkb3RzIC0gXHRoZXRhX3EgXHZhcmVwc2lsb25fe3QtcX0gXFwgJCQKCgpJbnRlZ3JhdGVkIChJKSB0ZXJtIChkKSByZWZlcnMgdG8gZGlmZmVyZW5jaW5nIHRoZSB0aW1lIHNlcmllcyBkYXRhIHRvIG1ha2UgaXQgc3RhdGlvbmFyeS4gU3RhdGlvbmFyaXR5IGlzIG9mdGVuIHJlcXVpcmVkIGZvciB0aW1lIHNlcmllcyBhbmFseXNpcywgYW5kIHRoZSBvcmRlciBvZiBkaWZmZXJlbmNpbmcgaXMgcmVwcmVzZW50ZWQgYnkgdGhlICJkIiBwYXJhbWV0ZXIuIAoKVGhlIEFSSU1BIGVxdWF0aW9uIDogCgokJCB5X3QgPSBcbXUgKyBccGhpXzEgeV97dC0xfSArIFxwaGlfMiB5X3t0LTJ9ICsgXGxkb3RzICsgXHBoaV9wIHlfe3QtcH0gKyBcZXBzaWxvbl90IC0gXHRoZXRhXzEgXGVwc2lsb25fe3QtMX0gLSBcdGhldGFfMiBcZXBzaWxvbl97dC0yfSAtIFxsZG90cyAtIFx0aGV0YV9xIFxlcHNpbG9uX3t0LXF9IFxcIAokJCAkJCAKXGJlZ2lue2FsaWduKn0KXHRleHR7V2hlcmV9OlxcCiZ5X3QgXHRleHR7IGlzIHRoZSBvYnNlcnZlZCB0aW1lIHNlcmllcyBhdCB0aW1lIH0gdCwgXFwKJlxtdSBcdGV4dHsgaXMgdGhlIG1lYW4gb2YgdGhlIHRpbWUgc2VyaWVzLH0gXFwKJlxlcHNpbG9uX3QgXHRleHR7IGlzIHRoZSB3aGl0ZSBub2lzZSBlcnJvciB0ZXJtIGF0IHRpbWUgfSB0LCBcXAomXHBoaV8xLCBccGhpXzIsIFxsZG90cywgXHBoaV9wIFx0ZXh0eyBhcmUgdGhlIGF1dG9yZWdyZXNzaXZlIChBUikgY29lZmZpY2llbnRzfSwgXFwKJnAgXHRleHR7IGlzIHRoZSBvcmRlciBvZiB0aGUgYXV0b3JlZ3Jlc3NpdmUgcGFydCx9IFxcCiZcdGhldGFfMSwgXHRoZXRhXzIsIFxsZG90cywgXHRoZXRhX3EgXHRleHR7IGFyZSB0aGUgbW92aW5nIGF2ZXJhZ2UgKE1BKSBjb2VmZmljaWVudHMsfSBcXAomcSBcdGV4dHsgaXMgdGhlIG9yZGVyIG9mIHRoZSBtb3ZpbmcgYXZlcmFnZSBwYXJ0Ln0KXGVuZHthbGlnbip9ClwKJCQKClRoZSAqKmF1dG8uYXJpbWEqKiBpcyBhIGZ1bmN0aW9uIGluIFIgKHBhcnQgb2YgdGhlIGZvcmVjYXN0IHBhY2thZ2UpIHRoYXQgYXV0b21hdGVzIHRoZSBzZWxlY3Rpb24gb2YgdGhlIGJlc3QgQVJJTUEgbW9kZWwgZm9yIGEgZ2l2ZW4gdGltZSBzZXJpZXMuIEZvciB0aGlzIHRpbWUgc2VyaXNlIGFuYWx5c2lzLCBJIHdpbGwgdXRpbGl6ZSB0aGUgYXV0by5hcmltYSAgc3VnZ2VzdGVkIG1vZGVscyBmb3IgZWFjaCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBzY2VuYXJpby4gVGhlIGZ1bmN0aW9uIHdpbGwgY29uZHVjdCBhIHNlYXJjaCBvdmVyIHBvc3NpYmxlIGNvbWJpbmF0aW9ucyBvZiBwLCBkLCBhbmQgcSBhbmQgc2VsZWN0cyB0aGUgbW9kZWwgd2l0aCB0aGUgbG93ZXN0IEFJQywgQklDIG9yIG90aGVyIGNyaXRlcmlhLiBUaGUgZ29hbCBpcyB0byBmaW5kIHRoZSBtb3N0IHN1aXRhYmxlIEFSSU1BIG1vZGVsIHdpdGhvdXQgdGhlIG5lZWQgZm9yIG1hbnVhbCB0cmlhbC1hbmQtZXJyb3IuCgoKIyMjIERyeSBGb29kcyBEYXRhOiBhdXRvLmFyaW1hIHN1Z2dlc3RlZCBtb2RlbAoKYGBge3IsZmlnLndpZHRoPTcsZmlnLmhlaWdodD0xMCxlY2hvPUZBTFNFfQoKZHJ5Zm9vZF9tb2RlbDwtYXV0by5hcmltYShkcnlmb29kKQpwcmludChkcnlmb29kX21vZGVsKQoKYGBgCgpUaGUgQVJJTUEoMCwwLDApKDAsMCwyKVsxMl0gbW9kZWwgd2l0aCBhIG5vbi16ZXJvIG1lYW4gaGFzIHRoZSBmb2xsb3dpbmcgZXF1YXRpb246CgokJCBcYmVnaW57YWxpZ24qfQp5X3QgJj0gMy4zNTkxIC0gMC4xNjQ0IFx2YXJlcHNpbG9uX3t0LTF9IC0gMC4xNjYwIFx2YXJlcHNpbG9uX3t0LTJ9ICsgXHZhcmVwc2lsb25fdCBcXApcZW5ke2FsaWduKn0KJCQKJCQgXGJlZ2lue2FsaWduKn0KXHRleHR7V2hlcmU6fVxcClx0ZXh0e3NtYTF9ICY9IC0wLjE2NDQgXHF1YWQgXHRleHR7KENvZWZmaWNpZW50IGZvciB0aGUgZmlyc3QgbW92aW5nIGF2ZXJhZ2UgdGVybSl9IFxcClx0ZXh0e3NtYTJ9ICY9IC0wLjE2NjAgXHF1YWQgXHRleHR7KENvZWZmaWNpZW50IGZvciB0aGUgc2Vjb25kIG1vdmluZyBhdmVyYWdlIHRlcm0pfSBcXApcdGV4dHttZWFufSAmPSAzLjM1OTEgXHF1YWQgXHRleHR7KE5vbi16ZXJvIG1lYW4gdGVybSl9IFxcClxzaWdtYV4yICY9IDAuNTY1MSBccXVhZCBcdGV4dHsoVmFyaWFuY2Ugb2YgdGhlIHdoaXRlIG5vaXNlIGVycm9yIHRlcm0pfSBcXApcdGV4dHtMb2cgbGlrZWxpaG9vZH0gJj0gLTE2OS4wOSBccXVhZCBcdGV4dHsoTG9nLWxpa2VsaWhvb2QgdmFsdWUpfSBcXApcdGV4dHtBSUN9ICY9IDM0Ni4xNyBccXVhZCBcdGV4dHsoQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbil9IFxcClx0ZXh0e0FJQ2N9ICY9IDM0Ni40NSBccXVhZCBcdGV4dHsoQ29ycmVjdGVkIEFJQyl9IFxcClx0ZXh0e0JJQ30gJj0gMzU4LjIyIFxxdWFkIFx0ZXh0eyhCYXllc2lhbiBJbmZvcm1hdGlvbiBDcml0ZXJpb24pfQpcZW5ke2FsaWduKn0KJCQKXG5ld3BhZ2UKCiMgRGlhZ25vc3RpYyBDaGVja2luZwoKIyMjIFNBUklNQSBNb2RlbAoKVGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKlNBUklNQSogIGlzIGFuIGV4dGVuc2lvbiBvZiB0aGUgQVJJTUEgbW9kZWwsIHNwZWNpZmljYWxseSBkZXNpZ25lZCB0byBoYW5kbGUgdGltZSBzZXJpZXMgZGF0YSB3aXRoIGEgc2Vhc29uYWwgY29tcG9uZW50LiBUaGlzIGJlY29tZXMgY3J1Y2lhbCB3aGVuIHRoZSB0aW1lIHNlcmllcyBleGhpYml0cyByZXBlYXRpbmcgcGF0dGVybnMgYXQgZml4ZWQgaW50ZXJ2YWxzLCBzdWNoIGFzIGRhaWx5LCBtb250aGx5LCBvciB5ZWFybHkgc2Vhc29uYWxpdHkuIEluIFNBUklNQSB0aGUgJ1MnIHN0YW5kcyBmb3IgU2Vhc29uYWwsIGFuZCB0aGUgbW9kZWwgYWNjb3VudHMgZm9yIHBlcmlvZGljIHBhdHRlcm5zIG9yIHRyZW5kcyBpbiB0aGUgZGF0YS4gQSBTQVJJTUEgbW9kZWwgaXMgZGVub3RlZCBhcyBTQVJJTUEocCwgZCwgcSkoUCwgRCwgUSlbc10sIHdoZXJlOgoKcCwgZCwgcTogTm9uLXNlYXNvbmFsIEFSSU1BIGNvbXBvbmVudHMuClAsIEQsIFE6IFNlYXNvbmFsIEFSSU1BIGNvbXBvbmVudHMuCnM6IFNlYXNvbmFsIHBlcmlvZC4KCkluIHRoaXMgYW5hbHlzaXMsIEkgd2lsbCBlbXBsb3kgdGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgKFNBUklNQSkgbW9kZWwgZm9yIHJlc2lkdWFsIGFuYWx5c2lzLgoKCiMjIyBEcnkgRm9vZHMgUmVzaWR1YWwgQ2hlY2tpbmcgCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKI3M8LSBzYXJpbWEoZGlmZl9kcnlmb29kLHA9MCxkPTAscT0xLFA9MCxEPTAsUT0xLFMgPSAxMikKczwtIHNhcmltYShkcnlmb29kLHA9MCxkPTAscT0wLFA9MCxEPTAsUT0yLFMgPSAxMikKCiNzPC1zYXJpbWEoZGlmZl9kcnlmb29kLDAsMCwxKQpgYGAKCgpGb3IgdGhlIERyeSBGb29kIGRhdGEgdGhlIGF1dG8uYXJpbWEgZnVuY3Rpb24gcmVjb21tZW5kZWQgQVJJTUEoMCwwLDApICgwLDAsMikgWzEyXSB0byBtb2RlbCB0aGUgcmVncmVzc2lvbiBlcnJvcnMuIENvZWZmaWNpZW50cyBhcmUgYXMgaW5kaWNhdGVkIGFib3ZlLiBUaGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBhcHBlYXIgc2F0aXNmYWN0b3J5LiBOb3RpY2U6IGh5cG90aGVzaXMgdGVzdGluZyBvZiB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSBjb2VmZmljaWVudHMgd2FzIHBlcmZvcm1lZCB1c2luZyB0aGUgc2FyaW1hIGZ1bmN0aW9uLiBUaGUgcC12YWx1ZXMgb2YgdGhlIExqdW5nLUJveCB0ZXN0IGFyZSBhbGwgYWJvdmUgemVybyBhbmQgYWJvdmUgdGhlIGdyaWRlIGxpbmUuClRoZSByZXNpZHVhbCBlcnJvcnMgYXBwZWFyIHRvIGhhdmUgYSBuZWFybHkgdW5pZm9ybSB2YXJpYW5jZSBhbmQgZmx1Y3R1YXRlIGFyb3VuZCBhIG1lYW4gb2YgemVybyAuIEZyb20gdGhlIE5vcm1hbCBRLVEgcGxvdCwgSSBjYW4gc2VlIHRoYXQgSSBhbG1vc3QgaGF2ZSBhIHN0cmFpZ2h0IGxpbmUsIGluZGljYXRpbmcgdGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIGRvZXNu4oCZdCBzZWVtIHRvIGJlIHZpb2xhdGVkLiBUaGUgY29ycmVsb2dyYW0sIGFsc28ga25vd24gYXMgdGhlIEFDRidzIGFyZSBhbGwgd2l0aGluIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwsIHN1Z2dlc3RzIHRoYXQgdGhlcmUgaXMgbm8gYXV0b2NvcnJlbGF0aW9uIGluIHRoZSByZXNpZHVhbHMuIE92ZXJhbGwsIHRoZSBmaXR0ZWQgbW9kZWwgbG9va3MgZ29vZC4KCiMjIFdldCBGb29kcyBEYXRhOiBhdXRvLmFyaW1hIHN1Z2dlc3RlZCBtb2RlbCAKYGBge3IsZmlnLndpZHRoPTcsZmlnLmhlaWdodD04LGVjaG89RkFMU0V9Cgp3ZXRmb29kX21vZGVsPC1hdXRvLmFyaW1hKHdldGZvb2QpCnByaW50KHdldGZvb2RfbW9kZWwpCgpgYGAKVGhlIEFSSU1BKDIsMCwyKSgyLDAsMClbMTJdIHN1Z2dlc3RlZCBtb2RlbCBmb3Igd2V0IGZvb2QgZGF0YSBjYW4gYmUgcmVwcmVzZW50ZWQgYXMgZm9sbG93czoKCiQkIFxiZWdpbnthbGlnbip9CnlfdCA9IC0xLjMwNDR5X3t0LTF9IC0gMC4zNzUzeV97dC0yfSArIDEuMTAzNFx2YXJlcHNpbG9uX3t0LTF9ICsgMC4xNDg4XHZhcmVwc2lsb25fe3QtMn0gKyAwLjAyMDhcYWxwaGFfe3QtMTJ9IC0gMC4wNDY4XGJldGFfe3QtMTJ9XjIgKyAyLjgzMjAgKyBcdmFyZXBzaWxvbl90IFxcClx0ZXh0YmZ7Q29lZmZpY2llbnRzOn0KXGJlZ2lue2FycmF5fXtjY2NjY2NjfQomIGFyMSAmIGFyMiAmIG1hMSAmIG1hMiAmIHNhcjEgJiBzYXIyICYgbWVhbiBcXApcdGV4dHtWYWx1ZX0gJiAtMS4zMDQ0ICYgLTAuMzc1MyAmIDEuMTAzNCAmIDAuMTQ4OCAmIDAuMDIwOCAmIC0wLjA0NjggJiAyLjgzMjAgXFwKXHRleHR7U3RhbmRhcmQgRXJyb3J9ICYgMC4zMTI4ICYgMC4zMDE5ICYgMC4zMjg0ICYgMC4zMTg1ICYgMC4wOTE0ICYgMC4xMDE4ICYgMC4wNDY3IFxcClxlbmR7YXJyYXl9ClxlbmR7YWxpZ24qfQokJAojIyBXZXQgRm9vZHMgUmVzaWR1YWwgQ2hlY2tpbmcKCkZvciB0aGUgV2V0IEZvb2RzIGRhdGEsIGF1dG8uYXJpbWEgZnVuY3Rpb24gcmVjb21tZW5kZWQgdGhlIEFSSU1BKDIsMCwyKSgyLDAsMClbMTJdIG1vZGVsLiBUaGUgY29lZmZpY2llbnRzIGFyZSBhcyBpbmRpY2F0ZWQgYmVsb3cgdXNpbmcgKipTQVJJTUEqKiBtb2RlbC4KCmBgYHtyLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9OCxlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQoKczE8LXNhcmltYSh3ZXRmb29kLHA9MixkPTAscT0yLFA9MixEPTAsUT0wLFMgPSAxMikKI3MxIDwtIHNhcmltYSh3ZXRmb29kLDAsMCwxKQoKYGBgCgpUaGUgcmVzaWR1YWxzIG9mIHRoZSBtb2RlbCBhcHBlYXIgc2F0aXNmYWN0b3J5LiBJdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgaHlwb3RoZXNpcyB0ZXN0aW5nIG9mIHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlIGNvZWZmaWNpZW50cyB3YXMgcGVyZm9ybWVkIHVzaW5nIHRoZSBzYXJpbWEgZnVuY3Rpb24uIFRoZSBwLXZhbHVlcyBvZiB0aGUgTGp1bmctQm94IHRlc3QgYXJlIGFsbCBhYm92ZSB6ZXJvIGFuZCBhYm92ZSB0aGUgc2lnbmlmaWNhbmNlIGxldmVsLCBpbmRpY2F0aW5nIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLgoKTW9yZW92ZXIsIHRoZSByZXNpZHVhbCBlcnJvcnMgZXhoaWJpdCBhIG5lYXJseSB1bmlmb3JtIHZhcmlhbmNlIGFuZCBmbHVjdHVhdGUgYXJvdW5kIGEgbWVhbiBvZiB6ZXJvLiBUaGUgTm9ybWFsIFEtUSBwbG90IHNob3dzIGEgbmVhcmx5IHN0cmFpZ2h0IGxpbmUsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgbm90IHZpb2xhdGVkLiBBZGRpdGlvbmFsbHksIHRoZSBjb3JyZWxvZ3JhbSAoQUNGKSBwbG90cyBhcmUgYWxsIHdpdGhpbiB0aGUgc2lnbmlmaWNhbmNlIGxldmVsLCBpbmRpY2F0aW5nIG5vIGF1dG9jb3JyZWxhdGlvbiBpbiB0aGUgcmVzaWR1YWxzLgoKSW4gc3VtbWFyeSwgYmFzZWQgb24gdmFyaW91cyBkaWFnbm9zdGljIGNoZWNrcywgdGhlIGZpdHRlZCBtb2RlbCBhcHBlYXJzIHRvIGJlIHdlbGwtc3VpdGVkIGZvciB0aGUgV2V0IEZvb2RzIGRhdGEsIGFuZCB0aGUgb3ZlcmFsbCBnb29kbmVzcy1vZi1maXQgaXMgc2F0aXNmYWN0b3J5LgoKCiMjIENvZWZmaWNpZW50cyBTdW1tYXJ5CgpgYGB7cixlY2hvPUZBTFNFfQpwYXIobWZyb3c9YygzLDEpKQprYWJsZShzJHR0YWJsZSxjYXB0aW9uID0gIkRyeSBGb29kcyBDb2VmZmljaWVudCBTdW1tYXJ5IikKa2FibGUoczEkdHRhYmxlLGNhcHRpb24gPSAiV2V0IEZvb2RzIENvZWZmaWNpZW50IFN1bW1hcnkiKQpgYGAKRnJvbSB0aGUgRHJ5IEZvb2RzIGNvZWZmaWNpZW50IHN1bW1hcnksICpzbWExKiBlc3RpbWF0ZSByZXByZXNlbnRzIHRoZSBlc3RpbWF0ZWQgY29lZmZpY2llbnQgZm9yIHRoZSBmaXJzdCB0ZXJtIGluIHRoZSBTQVJJTUEgbW9kZWwuIFRoZSBuZWdhdGl2ZSBlc3RpbWF0ZSBzdWdnZXN0cyBhbiBpbnZlcnNlIHJlbGF0aW9uc2hpcC4gVGhlIHQudmFsdWUgYW5kIHAudmFsdWUgcHJvdmlkZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIHRoaXMgY29lZmZpY2llbnQuIEluIHRoaXMgY2FzZSwgdGhlIHAudmFsdWUgaXMgZ3JlYXRlciB0aGFuIHRoZSBjb21tb24gc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUsIGluZGljYXRpbmcgdGhhdCB0aGUgY29lZmZpY2llbnQgbWlnaHQgbm90IGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgpTaW1pbGFyIHRvIHNtYTEsIHNtYTIgcmVwcmVzZW50cyB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50IGZvciB0aGUgc2Vjb25kIHRlcm0gaW4gdGhlIFNlYXNvbmFsIEF1dG9yZWdyZXNzaXZlIEludGVncmF0ZWQgTW92aW5nIEF2ZXJhZ2UgbW9kZWwuIFRoZSBuZWdhdGl2ZSBlc3RpbWF0ZSBpbXBsaWVzIGFuIGludmVyc2UgcmVsYXRpb25zaGlwLiBUaGUgdC52YWx1ZSBhbmQgcC52YWx1ZSBzdWdnZXN0IHRoYXQsIHNpbWlsYXIgdG8gc21hMSwgdGhpcyBjb2VmZmljaWVudCBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KClRoZSAqeG1lYW4qIHJlcHJlc2VudHMgdGhlIG1lYW4gdGVybS4gVGhlIGVzdGltYXRlIGluZGljYXRlcyB0aGUgZXN0aW1hdGVkIG1lYW4gdmFsdWUsIHRoZSBlc3RpbWF0ZSBpcyAzLjM1OTEsIHRoZSBzdGFuZGFyZCBlcnJvciBpcyAwLjA0MzgsIHRoZSB0LXZhbHVlIGlzIDc2LjY1OTQsIGFuZCB0aGUgcC12YWx1ZSBpcyAgemVyby4gVGhlIGhpZ2ggdC52YWx1ZSBhbmQgdmVyeSBsb3cgcC52YWx1ZSAgc3VnZ2VzdCB0aGF0IHRoZSBtZWFuIHRlcm0gaXMgaGlnaGx5IHNpZ25pZmljYW50LCBhbmQgdGhlIG1vZGVsIGhlYXZpbHkgcmVsaWVzIG9uIHRoaXMgdGVybS4gVGhlIGxvdyBwLnZhbHVlIGluZGljYXRlcyBhIGhpZ2ggbGV2ZWwgb2Ygc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlICJ4bWVhbiIgY29lZmZpY2llbnQgaXMgaGlnaGx5IHNpZ25pZmljYW50IGluIHRoZSBEcnkgRm9vZHMgbW9kZWwuCgpJbiB0aGUgY29lZmZpY2llbnQgc3VtbWFyeSBmb3IgdGhlIFdldCBGb29kcyBtb2RlbCwgKmFyMSogKEF1dG9SZWdyZXNzaXZlIHRlcm0gMSkgZXN0aW1hdGUgcmVwcmVzZW50cyB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50IGZvciB0aGUgZmlyc3QgdGVybSBpbiB0aGUgQVJJTUEgbW9kZWwudGhlIG5lZ2F0aXZlIGVzdGltYXRlIHN1Z2dlc3RzIGEgbmVnYXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGN1cnJlbnQgdmFsdWUgYW5kIGl0cyBwcmV2aW91cyB2YWx1ZS4gVGhlIHQudmFsdWUgaXMgcmVsYXRpdmVseSBsYXJnZSwgYW5kIHRoZSBsb3cgcC52YWx1ZSBpbmRpY2F0ZXMgdGhhdCB0aGlzIGNvZWZmaWNpZW50IGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIFNpbWlsYXIgdG8gYXIxLCBhcjIgcmVwcmVzZW50cyB0aGUgcmVsYXRpb25zaGlwIHdpdGggdGhlIHZhbHVlIHR3byB0aW1lIHBvaW50cyBhZ28uIFRoZSBlc3RpbWF0ZSBpcyBuZWdhdGl2ZSwgYnV0IHRoZSBwLnZhbHVlIGlzIHJlbGF0aXZlbHkgaGlnaCwgc3VnZ2VzdGluZyB0aGF0IHRoaXMgY29lZmZpY2llbnQgbWlnaHQgbm90IGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgoqbWExKiAoTW92aW5nIEF2ZXJhZ2UgdGVybSAxKSB0aGUgcG9zaXRpdmUgZXN0aW1hdGUgc3VnZ2VzdHMgYSBwb3NpdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgY3VycmVudCB2YWx1ZSBhbmQgdGhlIHJlc2lkdWFsIGZyb20gdGhlIHByZXZpb3VzIHBlcmlvZC4gVGhlIHQudmFsdWUgaXMgbGFyZ2UsIGFuZCB0aGUgbG93IHAudmFsdWUgaW5kaWNhdGVzIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZS4gU2ltaWxhciB0byBtYTEsIG1hMiByZXByZXNlbnRzIHRoZSByZWxhdGlvbnNoaXAgd2l0aCB0aGUgcmVzaWR1YWwgdHdvIHBlcmlvZHMgYWdvLiBUaGUgZXN0aW1hdGUgaXMgcG9zaXRpdmUsIGJ1dCB0aGUgcC52YWx1ZSBpcyBoaWdoLCBpbmRpY2F0aW5nIHRoYXQgdGhpcyBjb2VmZmljaWVudCBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCipzYXIxKiAoU2Vhc29uYWwgQXV0b1JlZ3Jlc3NpdmUgdGVybSAxKSwgIHRoZSBlc3RpbWF0ZSBpcyBjbG9zZSB0byB6ZXJvLCBhbmQgdGhlIGhpZ2ggcC52YWx1ZSBzdWdnZXN0cyB0aGF0IHRoaXMgc2Vhc29uYWwgQXV0b1JlZ3Jlc3NpdmUgdGVybSBtaWdodCBub3QgYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gU2ltaWxhciB0byBzYXIxLCBzYXIyIHJlcHJlc2VudHMgYSBzZWFzb25hbCByZWxhdGlvbnNoaXAuIFRoZSBlc3RpbWF0ZSBpcyBuZWdhdGl2ZSwgYnV0IHRoZSBwLnZhbHVlIGlzIGhpZ2gsIGluZGljYXRpbmcgcG90ZW50aWFsIGluc2lnbmlmaWNhbmNlLiAKCip4bWVhbiogdGhlIGVzdGltYXRlIHJlcHJlc2VudHMgdGhlIG1lYW4gdGVybS4gVGhlIGhpZ2ggdC52YWx1ZSBhbmQgdmVyeSBsb3cgcC52YWx1ZSBpbmRpY2F0ZSB0aGF0IHRoZSBtZWFuIHRlcm0gaXMgaGlnaGx5IHNpZ25pZmljYW50IGluIHRoaXMgbW9kZWwuCgoKIyMgQXNzZXNzbWVudCBvZiBGaXQKClRoZSAiTW9kZWwgU2NvcmVzIiByZXByZXNlbnQgdGhlIGV2YWx1YXRpb24gbWV0cmljcyBBSUMsIEFJQ2MsIEJJQyBmb3IgdGhlIGZvcmVjYXN0aW5nIG1vZGVsIHVzZWQgZm9yIGVhY2ggY2F0ZWdvcnkgRHJ5IEZvb2RzIGFuZCBXZXQgRm9vZHMuIEFJQyBpcyBhIG1lYXN1cmUgb2YgdGhlIG1vZGVsJ3MgZ29vZG5lc3Mgb2YgZml0LCBiYWxhbmNpbmcgdGhlIGFjY3VyYWN5IG9mIHRoZSBtb2RlbCB3aXRoIGl0cyBjb21wbGV4aXR5LiBMb3dlciBBSUMgdmFsdWVzIGluZGljYXRlIGJldHRlci1maXR0aW5nIG1vZGVscy4gQUlDYyBpcyBhIGNvcnJlY3Rpb24gdG8gQUlDLCBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBzbWFsbCBzYW1wbGUgc2l6ZXMuIFNpbWlsYXIgdG8gQUlDLCBsb3dlciBBSUNjIHZhbHVlcyBzdWdnZXN0IGJldHRlci1maXR0aW5nIG1vZGVscy4gQklDIGlzIGFub3RoZXIgY3JpdGVyaW9uIGZvciBtb2RlbCBzZWxlY3Rpb24gdGhhdCBwZW5hbGl6ZXMgY29tcGxleGl0eS4gTGlrZSBBSUMsIGxvd2VyIEJJQyB2YWx1ZXMgaW5kaWNhdGUgbW9kZWxzIHRoYXQgYmFsYW5jZSBhY2N1cmFjeSBhbmQgc2ltcGxpY2l0eS4gCgpgYGB7cixlY2hvPUZBTFNFfQoKa2FibGUoZGF0YS5mcmFtZShNb2RlbCA9IGMoIkRyeSBGb29kcyIsICJXZXQgRm9vZHMiKSwKICAgICAgICAgICAgICAgICBBSUMgPSBjKGRyeWZvb2RfbW9kZWwkYWljLHdldGZvb2RfbW9kZWwkYWljKSwKICAgICAgICAgICAgICAgICBBSUNjID0gYyhkcnlmb29kX21vZGVsJGFpY2Msd2V0Zm9vZF9tb2RlbCRhaWNjKSwKICAgICAgICAgICAgICAgICBCSUMgPSBjKGRyeWZvb2RfbW9kZWwkYmljLHdldGZvb2RfbW9kZWwkYmljKSksCiAgICAgIGNhcHRpb24gPSAnTW9kZWwgU2NvcmVzJykKCgpgYGAKVGhlIFdldCBGb29kcyBtb2RlbCBnZW5lcmFsbHkgaGFzIGxvd2VyIHZhbHVlcyBhY3Jvc3MgYWxsIHRocmVlIG1ldHJpY3MgKEFJQywgQUlDYywgQklDKSwgc3VnZ2VzdGluZyB0aGF0IGl0IG1heSBiZSBhIGJldHRlci1maXR0aW5nIGFuZCBsZXNzIGNvbXBsZXggbW9kZWwgY29tcGFyZWQgdG8gdGhlIERyeSBGb29kcyBtb2RlbC4KCgojIyBNb2RlbCBBY2N1cmFjeQoKYGBge3IsZWNobz1GQUxTRX0KIyBBc3N1bWluZyBkcnlmb29kX21vZGVsIGFuZCB3ZXRmb29kX21vZGVsIGFyZSB5b3VyIGZvcmVjYXN0aW5nIG1vZGVscwpkcnlmb29kX2FjY3VyYWN5IDwtIGFjY3VyYWN5KGRyeWZvb2RfbW9kZWwgJT4lIGZvcmVjYXN0KGggPSAxMikpCndldGZvb2RfYWNjdXJhY3kgPC0gYWNjdXJhY3kod2V0Zm9vZF9tb2RlbCAlPiUgZm9yZWNhc3QoaCA9IDEyKSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgYWNjdXJhY3kgbWV0cmljcwphY2N1cmFjeV9kZiA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gYygiRHJ5IEZvb2RzIiwgIldldCBGb29kcyIpLAogIE1FID0gYyhkcnlmb29kX2FjY3VyYWN5WzFdLCB3ZXRmb29kX2FjY3VyYWN5WzFdKSwKICBSTVNFID0gYyhkcnlmb29kX2FjY3VyYWN5WzJdLCB3ZXRmb29kX2FjY3VyYWN5WzJdKSwKICBNQUUgPSBjKGRyeWZvb2RfYWNjdXJhY3lbM10sIHdldGZvb2RfYWNjdXJhY3lbM10pLAogIE1QRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs0XSwgd2V0Zm9vZF9hY2N1cmFjeVs0XSksCiAgTUFQRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs1XSwgd2V0Zm9vZF9hY2N1cmFjeVs1XSksCiAgTUFTRSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs2XSwgd2V0Zm9vZF9hY2N1cmFjeVs2XSksCiAgQUNGMSA9IGMoZHJ5Zm9vZF9hY2N1cmFjeVs3XSwgd2V0Zm9vZF9hY2N1cmFjeVs3XSkKKQoKIyBQcmludCB0aGUgYWNjdXJhY3kgZGF0YSBmcmFtZQojcHJpbnQoYWNjdXJhY3lfZGYpCmBgYAoKCmBgYHtyLGVjaG89RkFMU0V9CmxpYnJhcnkoa25pdHIpCgojIENyZWF0ZSBhIGthYmxlIHRhYmxlCmthYmxlKAogIGFjY3VyYWN5X2RmLAogIGNhcHRpb24gPSAiKipNb2RlbCBBY2N1cmFjeSoqIiwKICBmb3JtYXQgPSAibWFya2Rvd24iLAogIGNvbC5uYW1lcyA9IGMoIk1vZGVsIiwgIk1FIiwgIlJNU0UiLCAiTUFFIiwgIk1QRSIsICJNQVBFIiwgIk1BU0UiLCAiQUNGMSIpCikKYGBgCgpUaGUgYWNjdXJhY3kgbWV0cmljcyBmb3IgdGhlIGZvcmVjYXN0aW5nIG1vZGVscyBvbiBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGluZGljYXRlIGEgcmVhc29uYWJseSBlZmZlY3RpdmUgcGVyZm9ybWFuY2Ugd2l0aCBzb21lIGNvbnNpZGVyYXRpb25zLgoKTWVhbiBFcnJvcjogVGhlIG1vZGVsIHRlbmRzIHRvIHNsaWdodGx5IHVuZGVyZXN0aW1hdGUgdGhlIGRlbWFuZCBmb3IgYm90aCBEcnkgRm9vZHMgYW5kIFdldCBGb29kcyBvbiBhdmVyYWdlLCB3aGljaCBtYXkgbmVlZCBmdXJ0aGVyIGludmVzdGlnYXRpb24gdG8gdW5kZXJzdGFuZCB0aGUgYmlhcy4KClJvb3QgTWVhbiBTcXVhcmVkIEVycm9yOiBUaGUgUk1TRSB2YWx1ZXMgYXJlIHJlbGF0aXZlbHkgbG93IGZvciBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgYXJlIGdlbmVyYWxseSBjbG9zZSB0byB0aGUgb2JzZXJ2ZWQgdmFsdWVzLgoKTWVhbiBBYnNvbHV0ZSBFcnJvcjogVGhlIE1BRSB2YWx1ZXMgYXJlIHJlYXNvbmFibGUsIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWwncyBhYnNvbHV0ZSBlcnJvcnMgYXJlIHJlbGF0aXZlbHkgc21hbGwgb24gYXZlcmFnZS4KCk1lYW4gUGVyY2VudGFnZSBFcnJvcjogVGhlIG5lZ2F0aXZlIE1QRSB2YWx1ZXMgaW5kaWNhdGUgYSBjb25zaXN0ZW50IHVuZGVyZXN0aW1hdGlvbiBvZiBkZW1hbmQuIEl0J3MgY3J1Y2lhbCB0byB1bmRlcnN0YW5kIHdoZXRoZXIgdGhpcyBiaWFzIGlzIGFjY2VwdGFibGUgZm9yIHRoZSBhcHBsaWNhdGlvbi4KCk1lYW4gQWJzb2x1dGUgUGVyY2VudGFnZSBFcnJvcjogVGhlIE1BUEUgdmFsdWVzLCB3aGlsZSBub3QgZXh0cmVtZWx5IGhpZ2gsIHN1Z2dlc3QgdGhhdCB0aGUgbW9kZWwncyBwZXJjZW50YWdlIGVycm9ycyBhcmUgbm90YWJsZS4gCgpNZWFuIEFic29sdXRlIFNjYWxlZCBFcnJvcjogQm90aCBNQVNFIHZhbHVlcyBhcmUgYmVsb3cgMSwgaW5kaWNhdGluZyB0aGF0IHRoZSBtb2RlbCBvdXRwZXJmb3JtcyBhIG5haXZlIGZvcmVjYXN0LCBidXQgdGhlcmUgaXMgcm9vbSBmb3IgaW1wcm92ZW1lbnQuCgpUaGUgKk1BUEUqIHZhbHVlcyBmb3IgYm90aCBtb2RlbHMgaW5kaWNhdGUgZmF2b3JhYmxlIGFjY3VyYWN5LCB0cmFuc2xhdGluZyB0byBhbiBlZmZlY3RpdmUgcHJlZGljdGlvbiAqYWNjdXJhY3kgb2YgYXBwcm94aW1hdGVseSA3Ny44JSogZm9yIERyeSBGb29kcyBhbmQgKjc1LjclKiBmb3IgV2V0IEZvb2RzIHdoZW4gc3VidHJhY3RlZCBmcm9tIDEwMCUuIFRoaXMgaW1wbGllcyB0aGF0IHRoZSBtb2RlbHMnIGZvcmVjYXN0cyBhcmUsIG9uIGF2ZXJhZ2UsIHdpdGhpbiBhIDIyLjIwJSBtYXJnaW4gb2YgZXJyb3IgZm9yIERyeSBGb29kcyBhbmQgYSAyNC4zMCUgbWFyZ2luIGZvciBXZXQgRm9vZHMsIHByb3ZpZGluZyBhIHNvbGlkIGJhc2lzIGZvciByZWxpYWJsZSBwcmVkaWN0aW9ucyBpbiB0aGUgY29udGV4dCBvZiBwZXQgZm9vZCBkZW1hbmQgZm9yZWNhc3RpbmcuT3ZlcmFsbCwgYm90aCBtb2RlbHMgc2VlbSB0byBwcm92aWRlIHJlYXNvbmFibGUgZm9yZWNhc3RzLCB3aXRoIHJlbGF0aXZlbHkgbG93IFJNU0UsIE1BRSwgYW5kIE1QRSB2YWx1ZXMuIFRoZSBhdXRvY29ycmVsYXRpb24gYXQgbGFnIDEgKEFDRjEpIGlzIGNsb3NlIHRvIHplcm8sIGluZGljYXRpbmcgdGhhdCB0aGUgbW9kZWxzIGhhdmUgY2FwdHVyZWQgdGhlIHRlbXBvcmFsIHBhdHRlcm5zIHdlbGwuCgoKCiMgUHJlZGljdGlvbiBQZXJmb3JtYW5jZQojIyBGb3JlY2FzdGluZwoKRnJvbSB0aGUgZGF0YXNldCAyMDIyIHRvIDIwMjMgd2FzIHJlc2VydmVkIHNwZWNpZmljYWxseSBmb3IgZXZhbHVhdGluZyB0aGUgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBvZiBlYWNoIG1vZGVsIGJ5IGFzc2Vzc2luZyB0aGVpciBhY2N1cmFjeS4gVXRpbGl6aW5nIHRoZSBmb3JlY2FzdCBmdW5jdGlvbiBmcm9tIHRoZSBmb3JlY2FzdCBwYWNrYWdlLCB0aGUgbW9kZWxzIGdlbmVyYXRlZCBwcmVkaWN0aW9ucyBmb3IgdGhlIG5leHQgMTIgbW9udGhzLCBmb3JlY2FzdGluZyBib3RoIERyeSBGb29kcyBhbmQgV2V0IEZvb2RzIGRlbWFuZC4KCmBgYHtyLGZpZy53aWR0aD02LjUsZmlnLmhlaWdodD0zLjUscmVzdWx0cz0naGlkZScsZmlnLnNob3c9J2hvbGQnLGVjaG89RkFMU0V9CgojIEZvcmVjYXN0IGFuZCBwbG90IGRyeSBmb29kCmRyeWZvb2RfbW9kZWwlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrIGF1dG9sYXllcihkcnlmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiRHJ5IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgRGF0YSIpICsgeWxhYigiRHJ5IEZvb2RzIikKCiMgRm9yZWNhc3QgYW5kIHBsb3Qgd2V0IGZvb2QKd2V0Zm9vZF9tb2RlbCU+JWZvcmVjYXN0KGg9MTIpJT4lYXV0b3Bsb3QoKSsKICBhdXRvbGF5ZXIod2V0Zm9vZF90ZXN0LHNlcmllcyA9ICJUZXN0IERhdGEiKSArIGdndGl0bGUoIldldCBGb29kIEZvcmVjYXN0IGZyb20gTG9nIFRyYW5zZm9ybWVkIERhdGEiKSArIAogIHlsYWIoIldldCBGb29kIikKCgoKYGBgCgpFYWNoIGdyYXBoIGluY2x1ZGVzIHRoZSBhY3R1YWwgdGVzdCBkYXRhIGluIG9yYW5nZSwgdGhlIG1lYW4gb2YgdGhlIHByZWRpY3Rpb24gaW4gYmx1ZSwgYW4gODAlIHByZWRpY3Rpb24gaW50ZXJ2YWwgcmVwcmVzZW50ZWQgYnkgYSBkZWVwIHB1cnBsZSBzaGFkZWQgYXJlYSwgYW5kIGEgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwgZGlzcGxheWVkIGFzIGEgbGlnaHQgcHVycGxlIHNoYWRlZCBhcmVhLiBUaGVzZSB2aXN1YWxpemF0aW9ucyBwcm92aWRlIGEgY29tcHJlaGVuc2l2ZSBvdmVydmlldyBvZiB0aGUgbW9kZWwncyBmb3JlY2FzdGluZyBjYXBhYmlsaXRpZXMgYW5kIHRoZWlyIGFsaWdubWVudCB3aXRoIHRoZSBhY3R1YWwgdGVzdCBkYXRhLgoKCiMjIEZvcmVjYXN0aW5nIGZyb20gT3JpZ2luYWwgRGF0YQoKTG9nIHRyYW5zZm9ybWF0aW9uIGlzIGEgY29tbW9uIHRlY2huaXF1ZSB1c2VkIGluIHRpbWUgc2VyaWVzIGZvcmVjYXN0aW5nIHRvIHN0YWJpbGl6ZSB2YXJpYW5jZSBhbmQgbWFrZSB0aGUgcGF0dGVybnMgaW4gdGhlIGRhdGEgbW9yZSBhcHBhcmVudC4gV2hlbiB0aGUgbG9nLXRyYW5zZm9ybWVkIHByZWRpY3Rpb25zIGNsb3NlbHkgdHJhY2sgdGhlIG9yaWdpbmFsIGRhdGEsIGl0IHN1Z2dlc3RzIHRoYXQgdGhlIGZvcmVjYXN0aW5nIG1vZGVsIGlzIGNhcHR1cmluZyB0aGUgdW5kZXJseWluZyBwYXR0ZXJucyBlZmZlY3RpdmVseS4gVGhlIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgYmx1ZSBsb2ctdHJhbnNmb3JtZWQgcHJlZGljdGlvbiBsaW5lIGFuZCB0aGUgb3JhbmdlIG9yaWdpbmFsIGRhdGEgbGluZSBpcyBhIHZpc3VhbCB3YXkgdG8gYXNzZXNzIHRoZSBhY2N1cmFjeSBhbmQgYWxpZ25tZW50IG9mIHRoZSBmb3JlY2FzdGVkIHZhbHVlcyB3aXRoIHRoZSBhY3R1YWwgb2JzZXJ2YXRpb25zCgpgYGB7cixlY2hvPUZBTFNFLGV2YWw9RkFMU0V9CgpwYXIobWZyb3c9YygzLDEpKQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHllYXIgb2YgMjAwMQpkcnlmb29kX2RhdGEgPC0gdHMocGV0X2RhdGEkIkRyeSBGb29kcyIsIHN0YXJ0ID0gYygyMDAxLCAxKSwgZW5kID0gYygyMDIzLCAyKSwgZnJlcXVlbmN5ID0gMTIpICAjIEFzc3VtaW5nIG1vbnRobHkgZGF0YSAoZnJlcXVlbmN5PTEyKQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIFdldCBGb29kcwp3ZXRmb29kX2RhdGEgPC0gdHMocGV0X2RhdGEkIldldCBGb29kcyIsIHN0YXJ0ID0gYygyMDAxLCAxKSwgZW5kID0gYygyMDIzLCAyKSwgZnJlcXVlbmN5ID0gMTIpICAjIEFzc3VtaW5nIG1vbnRobHkgZGF0YSAoZnJlcXVlbmN5PTEyKQoKIyBEcnkgRm9vZHMKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QgZm9yIERyeSBGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKI2RyeWZvb2RfZGF0YSA9IGxvZyhkcnlmb29kX2RhdGEpCmRyeWZvb2RfZGF0YSA8LSB0cyhwZXRfZGF0YSQiRHJ5IEZvb2RzIiwgc3RhcnQgPSBjKDIwMTAsIDEpLCBlbmQgPSBjKDIwMjMsIDIpLCBmcmVxdWVuY3kgPSAxMikgICMgQXNzdW1pbmcgbW9udGhseSBkYXRhIChmcmVxdWVuY3k9MTIpCgojIFNldCB0aGUgc3BsaXQgcG9pbnQgKGUuZy4sIDk1JSBmb3IgdHJhaW5pbmcsIDUlIGZvciB0ZXN0aW5nKQpzcGxpdF9wb2ludCA8LSBmbG9vcigwLjk1ICogbGVuZ3RoKGRyeWZvb2RfZGF0YSkpCgojIFNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cwpkcnlmb29kIDwtIHdpbmRvdyhkcnlmb29kX2RhdGEsIHN0YXJ0ID0gc3RhcnQoZHJ5Zm9vZF9kYXRhKSwgZW5kID0gdGltZShkcnlmb29kX2RhdGEpW3NwbGl0X3BvaW50XSkKCiMgQ3JlYXRlIHRoZSB0ZXN0aW5nIGRhdGEKZHJ5Zm9vZF90ZXN0IDwtIHdpbmRvdyhkcnlmb29kX2RhdGEsIHN0YXJ0ID0gdGltZShkcnlmb29kX2RhdGEpW3NwbGl0X3BvaW50ICsgMV0pCgojIENoZWNrIHRoZSBsZW5ndGhzIG9mIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEKbGVuZ3RoKGRyeWZvb2QpCmxlbmd0aChkcnlmb29kX3Rlc3QpCmhlYWQoZHJ5Zm9vZF90ZXN0KQp0YWlsKGRyeWZvb2RfdGVzdCkKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgb2JqZWN0IGZvciBXZXRGb29kcyBmcm9tIHRoZSB5ZWFyIDIwMTAKd2V0Zm9vZF9kYXRhIDwtIHRzKHBldF9kYXRhJCJXZXQgRm9vZHMiLCBzdGFydCA9IGMoMjAxMCwgMSksIGVuZCA9IGMoMjAyMywgMiksIGZyZXF1ZW5jeSA9IDEyKSAgIyBBc3N1bWluZyBtb250aGx5IGRhdGEgKGZyZXF1ZW5jeT0xMikKCiMgU2V0IHRoZSBzcGxpdCBwb2ludCAoZS5nLiwgOTglIGZvciB0cmFpbmluZywgNSUgZm9yIHRlc3RpbmcpCnNwbGl0X3BvaW50IDwtIGZsb29yKDAuOTggKiBsZW5ndGgod2V0Zm9vZF9kYXRhKSkKCiMgU3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzCndldGZvb2QgPC0gd2luZG93KHdldGZvb2RfZGF0YSwgc3RhcnQgPSBzdGFydCh3ZXRmb29kX2RhdGEpLCBlbmQgPSB0aW1lKHdldGZvb2RfZGF0YSlbc3BsaXRfcG9pbnRdKQoKIyBDcmVhdGUgdGhlIHRlc3RpbmcgZGF0YQp3ZXRmb29kX3Rlc3QgPC0gd2luZG93KHdldGZvb2RfZGF0YSwgc3RhcnQgPSB0aW1lKHdldGZvb2RfZGF0YSlbc3BsaXRfcG9pbnQgKyAxXSkKCiMgQ2hlY2sgdGhlIGxlbmd0aHMgb2YgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YQojbGVuZ3RoKHRyYWluX2RhdGEpCiNsZW5ndGgodGVzdF9kYXRhKQoKI2hlYWQoZHJ5Zm9vZCkKI3RhaWwoZHJ5Zm9vZCkKYGBgCgpgYGB7cixlY2hvPUZBTFNFLGV2YWw9RkFMU0UscmVzdWx0cz0naGlkZSd9CmRyeWZvb2RfbW9kZWwyPC1hdXRvLmFyaW1hKGRyeWZvb2QpCnByaW50KGRyeWZvb2RfbW9kZWwyKQoKd2V0Zm9vZF9tb2RlbDI8LWF1dG8uYXJpbWEod2V0Zm9vZCkKcHJpbnQod2V0Zm9vZF9tb2RlbDIpCgoKI3MxPC1zYXJpbWEod2V0Zm9vZCxwPTIsZD0wLHE9MixQPTIsRD0wLFE9MCxTID0gMTIpCiNzMSA8LSBzYXJpbWEod2V0Zm9vZCwwLDAsMSkKI3MxPC1zYXJpbWEod2V0Zm9vZCxwPTEsZD0wLHE9MCxQPTEsRD0wLFE9MCxTID0gMTIpCgpgYGAKCmBgYHtyLGZpZy53aWR0aD02LjUsZmlnLmhlaWdodD0zLjUscmVzdWx0cz0naGlkZScsZmlnLnNob3c9J2hvbGQnLGVjaG89RkFMU0V9CiNkcnlmb29kX21vZGVsJT4lZm9yZWNhc3QoaD0xMiklPiVhdXRvcGxvdCgpKwogI2F1dG9sYXllcihkcnlmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiRHJ5IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgRGF0YSIrIAogICN5bGFiKCJEcnkgRm9vZHMiKQoKZHJ5Zm9vZF9tb2RlbDIlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrCiAgYXV0b2xheWVyKGRyeWZvb2RfdGVzdCxzZXJpZXMgPSAiVGVzdCBEYXRhIikgKyBnZ3RpdGxlKCJEcnkgRm9vZHMgRm9yZWNhc3QgZnJvbSBPcmlnaW5hbCBEYXRhIikgKyAKICB5bGFiKCJEcnkgRm9vZHMiKQoKYGBgCgpgYGB7cixmaWcud2lkdGg9Ni41LGZpZy5oZWlnaHQ9My41LHJlc3VsdHM9J2hpZGUnLGZpZy5zaG93PSdob2xkJyxlY2hvPUZBTFNFfQoKI3dldGZvb2RfbW9kZWwlPiVmb3JlY2FzdChoPTEyKSU+JWF1dG9wbG90KCkrCiAgI2F1dG9sYXllcih3ZXRmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiV2V0IEZvb2QgRm9yZWNhc3QgZnJvbSBMb2cgVHJhbnNmb3JtZWQgI0RhdGEiKSArIHlsYWIoIldldCBGb29kIikKCndldGZvb2RfbW9kZWwyJT4lZm9yZWNhc3QoaD0xMiklPiVhdXRvcGxvdCgpKwogIGF1dG9sYXllcih3ZXRmb29kX3Rlc3Qsc2VyaWVzID0gIlRlc3QgRGF0YSIpICsgZ2d0aXRsZSgiV2V0IEZvb2RzIEZvcmVjYXN0IGZyb20gT3JpZ2luYWwgRGF0YSIpICsgCiAgeWxhYigiV2V0Rm9vZHMiKQoKYGBgCgpJbiB0aGUgY29udGV4dCBvZiB0aW1lIHNlcmllcyBmb3JlY2FzdGluZywgdGhlIHN0YXRlbWVudCBzdWdnZXN0cyB0aGF0IGFmdGVyIGFwcGx5aW5nIGEgbG9nIHRyYW5zZm9ybWF0aW9uIHRvIHRoZSBmb3JlY2FzdGVkIGRhdGEgZm9yIGJvdGggd2V0IGZvb2RzIGFuZCBkcnkgZm9vZHMsIHRoZSByZXN1bHRpbmcgcHJlZGljdGlvbiBsaW5lIGluIGJsdWUgY2xvc2VseSBmb2xsb3dzIHRoZSBhY3R1YWwgbGluZSBpbiBvcmFuZ2UuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIGxvZy10cmFuc2Zvcm1lZCBwcmVkaWN0aW9ucyBhbGlnbiB3ZWxsIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YS4KClxuZXdwYWdlCiMgRGF0YSBUcmFuc2Zvcm1hdGlvbiBhbmQgTXlTUUwgSW50ZWdyYXRpb24KCkFmdGVyIGZpbmlzaGluZyB0aGUgZm9yZWNhc3RpbmcgcHJvY2VzcywgbW92aW5nIHRoZSBkYXRhIHRvIGEgTXlTUUwgZGF0YWJhc2UgYW5kIHJ1bm5pbmcgc3BlY2lmaWMgcXVlcmllcyBiZWNvbWUgcmVhbGx5IGltcG9ydGFudC4gVGhpcyBoZWxwcyBhIGxvdCBpbiBtYWtpbmcgc21hcnQgZGVjaXNpb25zIGZvciBwbGFubmluZyBhbmQgYWxsb2NhdGluZyByZXNvdXJjZXMgc3RyYXRlZ2ljYWxseS4gVGhpcyBzdGVwIGFsbG93cyB1cyB0byBtZXJnZSB0aGUgZm9yZWNhc3RlZCBkYXRhIGludG8gYSB3ZWxsLW9yZ2FuaXplZCBkYXRhYmFzZS4gSXQgY3JlYXRlcyBhIGNlbnRyYWwgcGxhY2UgZm9yIGluZm9ybWF0aW9uLCBtYWtpbmcgaXQgZWFzaWVyIHRvIG1hbmFnZSBhbmQgYWNjZXNzLiBUaGlzIGFwcHJvYWNoIG5vdCBvbmx5IGltcHJvdmVzIGhvdyB3ZSBhY2Nlc3MgaW5mb3JtYXRpb24gYnV0IGFsc28gaGVscHMgaW4gbWFpbnRhaW5pbmcgdGhlIGRhdGFiYXNlIGVmZmljaWVudGx5LCBtYWtpbmcgZGVjaXNpb24gc3VwcG9ydCBzeXN0ZW1zIHdvcmsgYmV0dGVyLgoKIyMgTXlTUUwgRGF0YWJhc2UgYW5kIFF1ZXJ5CgpNeVNRTCBpcyBhbiBvcGVuLXNvdXJjZSByZWxhdGlvbmFsIGRhdGFiYXNlIG1hbmFnZW1lbnQgc3lzdGVtIHRoYXQgaXMgd2lkZWx5IHVzZWQgZm9yIG1hbmFnaW5nIGFuZCBvcmdhbml6aW5nIHN0cnVjdHVyZWQgZGF0YSBAbXlzcWwuIEl0IGlzIG9uZSBvZiB0aGUgbW9zdCBwb3B1bGFyIGRhdGFiYXNlcyBhbmQgaXMgY29tbW9ubHkgdXNlZCBmb3IgdmFyaW91cyBhcHBsaWNhdGlvbnMsIHJhbmdpbmcgZnJvbSBzbWFsbC1zY2FsZSB3ZWJzaXRlcyB0byBsYXJnZSBlbnRlcnByaXNlIHN5c3RlbXMuCgpNeVNRTCB3aWxsIGFjdCBhcyBhIHJlbGlhYmxlIGFuZCBzY2FsYWJsZSBiYWNrZW5kIGRhdGFiYXNlIGZvciB0aGlzIHByb2plY3QsIGJ5IHByb3ZpZGluZyBlc3NlbnRpYWwgY2FwYWJpbGl0aWVzIGZvciBlZmZpY2llbnRseSBzdG9yaW5nLCBvcmdhbml6aW5nLCBxdWVyeWluZywgYW5kIGludGVncmF0aW5nIGRhdGEuIEJlbG93IEkgYW0gZ29pbmcgdG8gcHJvdmlkZSBzb21lIGV4YW1wbGUgbGx1c3RyYXRpbmcgaG93IHNwZWNpZmljIGFuc3dlcnMgY2FuIGJlIG9idGFpbmVkIHRocm91Z2ggU1FMIHF1ZXJpZXMuCgotIElkZW50aWZ5aW5nIFVuZGVyc2VydmVkIFppcCBDb2RlIEFyZWFzOgoKYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iMTAwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCIvVXNlcnMvc2hhbWltYS9EZXNrdG9wL1Byb2plY3RfMS9pbWFnZXMvUGljdHVyZTEucG5nIiwgZXJyb3IgPSBGQUxTRSkKCmBgYAoKCkJ5IGFuYWx5emluZyB0aGUgZGF0YSwgdGhlIG9yZ2FuaXphdGlvbiBjYW4gcGlucG9pbnQgemlwIGNvZGUgYXJlYXMgdGhhdCBhcmUgdW5kZXJzZXJ2ZWQgaW4gdGVybXMgb2YgcGV0IGZvb2QgZGVtYW5kLiBUaGlzIGluZm9ybWF0aW9uIGlzIHZhbHVhYmxlIGZvciBkaXJlY3Rpbmcgb3V0cmVhY2ggZWZmb3J0cyBhbmQgZW5zdXJpbmcgdGhhdCByZXNvdXJjZXMgYXJlIGFsbG9jYXRlZCB0byBhcmVhcyB3aXRoIHRoZSBncmVhdGVzdCBuZWVkLgoKXG5ld3BhZ2UKLSBBbmFseXppbmcgRm9vZHMgRGVtYW5kIGJ5IFBldCBUeXBlIGFuZCBEaXN0cmlidXRpb24gQXJlYXM6CmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL3NoYW1pbWEvRGVza3RvcC9Qcm9qZWN0XzEvaW1hZ2VzL1BpY3R1cmUyLnBuZyIsIGVycm9yID0gRkFMU0UpCgpgYGAKVGhlIGRhdGEgYW5hbHlzaXMgYWxsb3dzIGZvciBhIGRldGFpbGVkIGV4YW1pbmF0aW9uIG9mIHBldCBmb29kIGRlbWFuZCBjYXRlZ29yaXplZCBieSBwZXQgdHlwZS4gVGhpcyBpbnNpZ2h0IGhlbHBzIHRoZSBvcmdhbml6YXRpb24gdW5kZXJzdGFuZCB0aGUgdmFyeWluZyBuZWVkcyBvZiBkaWZmZXJlbnQgdHlwZXMgb2YgcGV0cyBhbmQgc3RyYXRlZ2ljYWxseSBwbGFuIGZvb2QgZGlzdHJpYnV0aW9uIGluIHNwZWNpZmljIGFyZWFzLgoKLSBJZGVudGlmeWluZyBIaWdoZXN0IE5lZWQgQXJlYXMgYnkgTnVtYmVyIG9mIFBldHM6CgpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSIxMDAlIn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9zaGFtaW1hL0Rlc2t0b3AvUHJvamVjdF8xL2ltYWdlcy9QaWN0dXJlMy5wbmciLCBlcnJvciA9IEZBTFNFKQoKYGBgClRoZSBkYXRhIHdpbGwgcmV2ZWFsIGFyZWFzIHdpdGggdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiBvZiBwZXRzLCBpbmRpY2F0aW5nIHJlZ2lvbnMgd2hlcmUgdGhlIGRlbWFuZCBmb3IgcGV0IGZvb2QgaXMgcGFydGljdWxhcmx5IGhpZ2guIFRoaXMga25vd2xlZGdlIGlzIGVzc2VudGlhbCBmb3IgcHJpb3JpdGl6aW5nIGVmZm9ydHMgYW5kIHJlc291cmNlcyB0byBhZGRyZXNzIHRoZSBuZWVkcyBvZiBjb21tdW5pdGllcyB3aXRoIGEgbGFyZ2VyIG51bWJlciBvZiBwZXRzLgpJbiBzdW1tYXJ5LCB0aGUgb3V0Y29tZXMgb2YgdGhpcyBhbmFseXNpcyB3aWxsIHByb3ZpZGUgYSBjb21wcmVoZW5zaXZlIHZpZXcgb2YgdGhlIG9yZ2FuaXphdGlvbidzIG9wZXJhdGlvbmFsIGxhbmRzY2FwZSwgZW5hYmxpbmcgdGFyZ2V0ZWQgaW50ZXJ2ZW50aW9ucyBhbmQgc3RyYXRlZ2ljIGRlY2lzaW9ucyB0byBhZGRyZXNzIHNwZWNpZmljIG5lZWRzIGluIGRpZmZlcmVudCBhcmVhcy4KCkluIHN1bW1hcnksIHRoZSBvdXRjb21lcyBvZiB0aGlzIGFuYWx5c2lzIHdpbGwgcHJvdmlkZSBhIGNvbXByZWhlbnNpdmUgdmlldyBvZiB0aGUgb3JnYW5pemF0aW9uJ3Mgb3BlcmF0aW9uYWwgbGFuZHNjYXBlLCBlbmFibGluZyB0YXJnZXRlZCBpbnRlcnZlbnRpb25zIGFuZCBzdHJhdGVnaWMgZGVjaXNpb25zIHRvIGFkZHJlc3Mgc3BlY2lmaWMgbmVlZHMgaW4gZGlmZmVyZW50IGFyZWFzLgoKIyBMaW1pdGF0aW9ucwoKVGhlIHByZWNpc2lvbiBvZiB0aGUgZm9yZWNhc3RpbmcgbW9kZWxzIHJlbGllcyBzaWduaWZpY2FudGx5IG9uIHRoZSBxdWFsaXR5IG9mIHRoZSBpbnB1dCBkYXRhLiBJbiB0aGlzIHByb2plY3QsIHRoZSBoaXN0b3JpY2FsIGRhdGEgcHJlc2VudHMgY2hhbGxlbmdlcyB3aXRoIGluYWNjdXJhY2llcyBhbmQgbWlzc2luZyB2YWx1ZXMsIHBvdGVudGlhbGx5IGFmZmVjdGluZyB0aGUgZGVwZW5kYWJpbGl0eSBvZiBteSBmb3JlY2FzdHMuIFRoZSBoaXN0b3JpY2FsIGRhdGEgYXZhaWxhYmlsaXR5LCBwYXJ0aWN1bGFybHkgaW4gdGhlIGVhcmx5IHllYXJzLCBpcyBjb25zdHJhaW5lZCwgcG9zaW5nIGh1cmRsZXMgZm9yIHRoZSBmb3JlY2FzdGluZyBtb2RlbHMuIEFkZGl0aW9uYWxseSwgdGhlc2UgbW9kZWxzIG1heSBzdHJ1Z2dsZSB0byBmdWxseSBhY2NvdW50IGZvciBleHRlcm5hbCBmYWN0b3JzIGxpa2Ugc2hpZnRzIGluIGVjb25vbWljIGNvbmRpdGlvbnMsIHB1YmxpYyBoZWFsdGggY3Jpc2VzLCBvciB1bmV4cGVjdGVkIGV2ZW50cyB0aGF0IGNvdWxkIHNpZ25pZmljYW50bHkgaW5mbHVlbmNlIHRoZSBkZW1hbmQgZm9yIHBldCBmb29kLgoKIyBGdXR1cmUgUmVzZWFyY2ggQXJlYXMKCmltcGxlbWVudGluZyB0aGUgc3RvcmFnZSBhbmQgcmV0cmlldmFsIG9mIGRhdGEgaW4gYSBNeVNRTCBkYXRhYmFzZSBpbnZvbHZlcyBjcmVhdGluZyB0YWJsZXMgd2l0aCB1bmlxdWUgaWRlbnRpZmllcnMgZm9yIGN1c3RvbWVycyBhbmQgb3JkZXIgZGV0YWlscy4gVGhpcyBzdGVwIGVuaGFuY2VzIGRhdGEgb3JnYW5pemF0aW9uIGFuZCBhY2Nlc3NpYmlsaXR5LCBsYXlpbmcgdGhlIGZvdW5kYXRpb24gZm9yIG1vcmUgaW4tZGVwdGggYW5hbHlzZXMgYW5kIGltcHJvdmVkIGRhdGEgbWFuYWdlbWVudC4gCkFkZGl0aW9uYWxseSwgZGlmZmVyZW50aWF0aW5nIGZvcmVjYXN0aW5nIG1vZGVscyBmb3Igc3BlY2lmaWMgcGV0IHR5cGVzLCBzdWNoIGFzIGNhdHMgb3IgZG9ncywgY291bGQgb2ZmZXIgbW9yZSBkZXRhaWxlZCBpbnNpZ2h0cyBpbnRvIHRoZSBkZW1hbmQgcGF0dGVybnMgd2l0aGluIGVhY2ggY2F0ZWdvcnkuIFRoaXMgYXBwcm9hY2ggYWxsb3dzIGZvciBhIG1vcmUgbnVhbmNlZCB1bmRlcnN0YW5kaW5nIG9mIHRoZSB1bmlxdWUgZmFjdG9ycyBpbmZsdWVuY2luZyB0aGUgZGVtYW5kIGZvciBkaWZmZXJlbnQgdHlwZXMgb2YgcGV0cy4KCiMgQ29uY2x1c2lvbnMKClRoaXMgcHJvamVjdCBoYXMgYmVlbiBhIGR5bmFtaWMgam91cm5leSwgbmF2aWdhdGluZyB0aGUgaW50cmljYWNpZXMgb2YgZGF0YSBhbmFseXNpcywgbW9kZWxpbmcsIGFuZCBkZWNpc2lvbi1tYWtpbmcuIFRoZSBlbmRlYXZvciB0byB1bnJhdmVsIHBhdHRlcm5zIGFuZCBhbnRpY2lwYXRlIHRyZW5kcyBpbiBwZXQgZm9vZCBkZW1hbmQgaGFzIGJlZW4gZHJpdmVuIGJ5IGEgbWV0aWN1bG91cyBleGFtaW5hdGlvbiBvZiBoaXN0b3JpY2FsIGRhdGEgYW5kIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiByb2J1c3QgZm9yZWNhc3RpbmcgbW9kZWxzLgpUaGUgcHJvamVjdCBub3Qgb25seSBhZHZhbmNlcyB0aGUgdW5kZXJzdGFuZGluZyBvZiBkZW1hbmQgZm9yZWNhc3RpbmcgaW4gdGhlIHBldCBmb29kIGluZHVzdHJ5IGJ1dCBhbHNvIHNldHMgdGhlIHN0YWdlIGZvciBjb250aW51ZWQgcmVzZWFyY2ggYW5kIHJlZmluZW1lbnQuIFRoZSBpbnRlZ3JhdGlvbiBvZiBNWVNRTCBkYXRhIHRyYW5zZm9ybWF0aW9uIG5vdCBvbmx5IGVuaGFuY2VzIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgYW5hbHlzZXMgYnV0IG9wZW5zIGF2ZW51ZXMgZm9yIG1vcmUgc3BlY2lmaWMgcXVlc3Rpb25zIGFuZCBhbnN3ZXJzLiBCeSBkZWx2aW5nIGludG8gcGV0IGZvb2QgZGVtYW5kIHdpdGggYSBmaW5lciBsZW5zLCB0aGF0IGNhbiB1bmNvdmVyIG51YW5jZXMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgb2JzY3VyZWQuCgpUaGlzIHByb2plY3Qgd2lsbCBlbXBvd2VyIHRoZSBvcmdhbml6YXRpb24gdG8gYWRlcHRseSBjb21wcmVoZW5kIGFuZCBvdmVyc2VlIGl0cyBwZXQgZm9vZCBiYW5rLiBUaGUgZGFzaGJvYXJkIGVtZXJnZXMgYXMgYW4gaW52YWx1YWJsZSB0b29sLCBlc3BlY2lhbGx5IGZvciBmdW5kcmFpc2luZyBhbmQgb3V0cmVhY2ggaW5pdGlhdGl2ZXMsIHBhcnRpY3VsYXJseSBpbiBjb21tdW5pdGllcyB3aXRoIGhpZ2hlciBuZWVkcy4gQWxvbmdzaWRlIHRhcmdldGVkIHF1ZXJpZXMsIGl0IGFkZGl0aW9uYWxseSBlbmhhbmNlcyB0aGUgY2FwYWNpdHkgZm9yIGluZm9ybWVkIGRlY2lzaW9uLW1ha2luZyBpbiBzdHJhdGVnaWMgcGxhbm5pbmcgYW5kIHJlc291cmNlIGFsbG9jYXRpb24uCgoKXG5ld3BhZ2UKCiMgQmlibGlvZ3JhcGh5CgoK